From 7095a53bf173ca6680c7888c8d1df4afb1ad29ae Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Sat, 27 Sep 2025 15:10:13 -0700 Subject: add pr-analyzer A tool to analyze pull request review patterns in a GitHub repository, focusing on team members' review behaviors and habits. This tool helps teams understand and improve their code review processes by providing insights into review frequency, speed, thoroughness, and approval patterns. --- cmd/pr-analyzer/types.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 cmd/pr-analyzer/types.go (limited to 'cmd/pr-analyzer/types.go') diff --git a/cmd/pr-analyzer/types.go b/cmd/pr-analyzer/types.go new file mode 100644 index 0000000..4c3a83d --- /dev/null +++ b/cmd/pr-analyzer/types.go @@ -0,0 +1,105 @@ +package main + +import ( + "time" +) + +// PRData represents a pull request with its reviews and comments. +type PRData struct { + // Number is the pull request number + Number int + // CreatedAt is the timestamp when the PR was created + CreatedAt time.Time + // Reviews contains all reviews submitted for this PR + Reviews []ReviewData +} + +// ReviewData represents a review submitted on a pull request. +type ReviewData struct { + // Reviewer is the GitHub username of the person who submitted the review + Reviewer string + // State represents the review state: APPROVED, CHANGES_REQUESTED, or COMMENTED + State string + // SubmittedAt is the timestamp when the review was submitted + SubmittedAt time.Time + // Comments contains all inline comments made during the review + Comments []CommentData +} + +// CommentData represents an inline comment made during a review. +type CommentData struct { + // Reviewer is the GitHub username of the person who made the comment + Reviewer string + // CreatedAt is the timestamp when the comment was created + CreatedAt time.Time + // Path is the file path where the comment was made + Path string + // Line is the line number where the comment was made + Line int +} + +// ReviewerMetrics holds the analysis results for a single reviewer. +type ReviewerMetrics struct { + // Username is the GitHub username of the reviewer + Username string + // PRsReviewed is the total number of PRs reviewed by this person + PRsReviewed int + // AverageReviewSpeed is the average time (in hours) from PR creation + // to the reviewer's first comment + AverageReviewSpeed float64 // in hours + // AverageComments is the average number of inline comments made + // per PR when the reviewer comments + AverageComments float64 + // ImmediateApprovals is the percentage of PRs that were approved + // without requesting changes first + ImmediateApprovals float64 // percentage +} + +// ReviewPattern represents the approval pattern for a PR. +type ReviewPattern struct { + // IsImmediateApproval indicates if the PR was approved without + // requesting changes first + IsImmediateApproval bool + // FirstReviewState is the state of the first review submitted + FirstReviewState string + // FinalReviewState is the state of the last review submitted + FinalReviewState string + // TimeToFirstReview is the duration from PR creation to first review + TimeToFirstReview time.Duration + // TimeToFinalReview is the duration from PR creation to final review + TimeToFinalReview time.Duration +} + +// PRMetrics holds all metrics for a single PR. +type PRMetrics struct { + // Number is the pull request number + Number int + // CreatedAt is the timestamp when the PR was created + CreatedAt time.Time + // ReviewPatterns contains the review patterns for each reviewer + ReviewPatterns []ReviewPattern + // CommentsPerFile maps file paths to the number of comments made + // on that file + CommentsPerFile map[string]int + // Reviewers is the list of GitHub usernames who reviewed this PR + Reviewers []string + // TimeToFirstReview is the duration from PR creation to the first + // review being submitted + TimeToFirstReview time.Duration +} + +// Analyzer processes PR data and generates metrics. +type Analyzer struct { + // startDate is the beginning of the analysis period + startDate time.Time + // endDate is the end of the analysis period + endDate time.Time +} + +// NewAnalyzer creates a new PR analyzer with the specified date range. +func NewAnalyzer(startDate, endDate time.Time) *Analyzer { + return &Analyzer{ + startDate: startDate, + endDate: endDate, + } +} -- cgit v1.2.3