mirror of
https://github.com/lukaszraczylo/git-velocity.git
synced 2026-06-06 22:49:27 +00:00
112 lines
3.1 KiB
Go
112 lines
3.1 KiB
Go
package models
|
|
|
|
import "time"
|
|
|
|
// PRState represents the state of a pull request
|
|
type PRState string
|
|
|
|
const (
|
|
PRStateOpen PRState = "open"
|
|
PRStateClosed PRState = "closed"
|
|
PRStateMerged PRState = "merged"
|
|
)
|
|
|
|
// PullRequest represents a GitHub pull request
|
|
type PullRequest struct {
|
|
Number int `json:"number"`
|
|
Title string `json:"title"`
|
|
State PRState `json:"state"`
|
|
Author Author `json:"author"`
|
|
Repository string `json:"repository"` // owner/repo format
|
|
BaseBranch string `json:"base_branch"` // Target branch (e.g., main, master)
|
|
HeadBranch string `json:"head_branch"` // Source branch
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
MergedAt *time.Time `json:"merged_at,omitempty"`
|
|
ClosedAt *time.Time `json:"closed_at,omitempty"`
|
|
Additions int `json:"additions"`
|
|
Deletions int `json:"deletions"`
|
|
FilesChanged int `json:"files_changed"`
|
|
CommitCount int `json:"commit_count"`
|
|
Comments int `json:"comments"`
|
|
Reviews []Review `json:"reviews,omitempty"`
|
|
URL string `json:"url"`
|
|
|
|
// Meaningful line counts (excludes comments and whitespace)
|
|
MeaningfulAdditions int `json:"meaningful_additions"`
|
|
MeaningfulDeletions int `json:"meaningful_deletions"`
|
|
|
|
// Derived fields
|
|
TimeToMerge *time.Duration `json:"time_to_merge,omitempty"`
|
|
TimeToFirstReview *time.Duration `json:"time_to_first_review,omitempty"`
|
|
}
|
|
|
|
// IsMerged returns true if the PR has been merged
|
|
func (pr *PullRequest) IsMerged() bool {
|
|
return pr.State == PRStateMerged || pr.MergedAt != nil
|
|
}
|
|
|
|
// TotalChanges returns the total lines changed (additions + deletions)
|
|
func (pr *PullRequest) TotalChanges() int {
|
|
return pr.Additions + pr.Deletions
|
|
}
|
|
|
|
// CalculateTimeToMerge calculates the time from PR creation to merge
|
|
func (pr *PullRequest) CalculateTimeToMerge() *time.Duration {
|
|
if pr.MergedAt == nil {
|
|
return nil
|
|
}
|
|
d := pr.MergedAt.Sub(pr.CreatedAt)
|
|
return &d
|
|
}
|
|
|
|
// CalculateTimeToFirstReview calculates the time from PR creation to first review
|
|
func (pr *PullRequest) CalculateTimeToFirstReview() *time.Duration {
|
|
if len(pr.Reviews) == 0 {
|
|
return nil
|
|
}
|
|
|
|
var firstReview *time.Time
|
|
for _, review := range pr.Reviews {
|
|
if firstReview == nil || review.SubmittedAt.Before(*firstReview) {
|
|
t := review.SubmittedAt
|
|
firstReview = &t
|
|
}
|
|
}
|
|
|
|
if firstReview == nil {
|
|
return nil
|
|
}
|
|
|
|
d := firstReview.Sub(pr.CreatedAt)
|
|
return &d
|
|
}
|
|
|
|
// PRSize represents the size category of a pull request
|
|
type PRSize string
|
|
|
|
const (
|
|
PRSizeXS PRSize = "xs" // < 10 lines
|
|
PRSizeS PRSize = "s" // 10-50 lines
|
|
PRSizeM PRSize = "m" // 50-200 lines
|
|
PRSizeL PRSize = "l" // 200-500 lines
|
|
PRSizeXL PRSize = "xl" // > 500 lines
|
|
)
|
|
|
|
// Size returns the size category of the PR based on total changes
|
|
func (pr *PullRequest) Size() PRSize {
|
|
total := pr.TotalChanges()
|
|
switch {
|
|
case total < 10:
|
|
return PRSizeXS
|
|
case total < 50:
|
|
return PRSizeS
|
|
case total < 200:
|
|
return PRSizeM
|
|
case total < 500:
|
|
return PRSizeL
|
|
default:
|
|
return PRSizeXL
|
|
}
|
|
}
|