diff --git a/docs/configuration.md b/docs/configuration.md index e1e4ab7..1b02af4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1201,6 +1201,7 @@ Example: repository: glanceapp/glance pull-requests-limit: 5 issues-limit: 3 + commits-limit: 3 ``` Preview: @@ -1215,6 +1216,7 @@ Preview: | token | string | no | | | pull-requests-limit | integer | no | 3 | | issues-limit | integer | no | 3 | +| commits-limit | integer | no | -1 | ##### `repository` The owner and repository name that will have their information displayed. @@ -1228,6 +1230,9 @@ The maximum number of latest open pull requests to show. Set to `-1` to not show ##### `issues-limit` The maximum number of latest open issues to show. Set to `-1` to not show any. +##### `commits-limit` +The maximum number of lastest commits to show from the default branch. Set to `-1` to not show any. + ### Bookmarks Display a list of links which can be grouped. diff --git a/internal/assets/templates/repository.html b/internal/assets/templates/repository.html index 26048dc..53b6617 100644 --- a/internal/assets/templates/repository.html +++ b/internal/assets/templates/repository.html @@ -7,6 +7,23 @@
  • {{ .RepositoryDetails.Forks | formatNumber }} forks
  • +{{ if gt (len .RepositoryDetails.Commits) 0 }} +
    +Last {{ .CommitsLimit }} commits +
    + + +
    +{{ end }} + {{ if gt (len .RepositoryDetails.PullRequests) 0 }}
    Open pull requests ({{ .RepositoryDetails.OpenPullRequests | formatNumber }} total) diff --git a/internal/feed/github.go b/internal/feed/github.go index 8adbfd8..782d612 100644 --- a/internal/feed/github.go +++ b/internal/feed/github.go @@ -3,6 +3,7 @@ package feed import ( "fmt" "net/http" + "strings" "sync" "time" ) @@ -67,6 +68,8 @@ type RepositoryDetails struct { PullRequests []GithubTicket OpenIssues int Issues []GithubTicket + LastCommits int + Commits []CommitDetails } type githubRepositoryDetailsResponseJson struct { @@ -84,21 +87,40 @@ type githubTicketResponseJson struct { } `json:"items"` } -func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs int, maxIssues int) (RepositoryDetails, error) { - repositoryRequest, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s", repository), nil) +type CommitDetails struct { + Sha string + Author string + CreatedAt time.Time + Message string +} +type gitHubCommitResponseJson struct { + Sha string `json:"sha"` + Commit struct { + Author struct { + Name string `json:"name"` + Date string `json:"date"` + } `json:"author"` + Message string `json:"message"` + } `json:"commit"` +} + +func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs int, maxIssues int, maxCommits int) (RepositoryDetails, error) { + repositoryRequest, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s", repository), nil) if err != nil { return RepositoryDetails{}, fmt.Errorf("%w: could not create request with repository: %v", ErrNoContent, err) } PRsRequest, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/search/issues?q=is:pr+is:open+repo:%s&per_page=%d", repository, maxPRs), nil) issuesRequest, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/search/issues?q=is:issue+is:open+repo:%s&per_page=%d", repository, maxIssues), nil) + CommitsRequest, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s/commits?per_page=%d", repository, maxCommits), nil) if token != "" { token = fmt.Sprintf("Bearer %s", token) repositoryRequest.Header.Add("Authorization", token) PRsRequest.Header.Add("Authorization", token) issuesRequest.Header.Add("Authorization", token) + CommitsRequest.Header.Add("Authorization", token) } var detailsResponse githubRepositoryDetailsResponseJson @@ -107,6 +129,8 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in var PRsErr error var issuesResponse githubTicketResponseJson var issuesErr error + var commitsResponse []gitHubCommitResponseJson + var CommitsErr error var wg sync.WaitGroup wg.Add(1) @@ -131,6 +155,14 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in })() } + if maxCommits > 0 { + wg.Add(1) + go (func() { + defer wg.Done() + commitsResponse, CommitsErr = decodeJsonFromRequest[[]gitHubCommitResponseJson](defaultClient, CommitsRequest) + })() + } + wg.Wait() if detailsErr != nil { @@ -143,6 +175,7 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in Forks: detailsResponse.Forks, PullRequests: make([]GithubTicket, 0, len(PRsResponse.Tickets)), Issues: make([]GithubTicket, 0, len(issuesResponse.Tickets)), + Commits: make([]CommitDetails, 0, len(commitsResponse)), } err = nil @@ -180,5 +213,20 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in } } + if maxCommits > 0 { + if CommitsErr != nil { + err = fmt.Errorf("%w: could not get issues: %s", ErrPartialContent, CommitsErr) + } else { + for i := range commitsResponse { + details.Commits = append(details.Commits, CommitDetails{ + Sha: commitsResponse[i].Sha, + Author: commitsResponse[i].Commit.Author.Name, + CreatedAt: parseRFC3339Time(commitsResponse[i].Commit.Author.Date), + Message: strings.SplitN(commitsResponse[i].Commit.Message, "\n\n", 2)[0], + }) + } + } + } + return details, err } diff --git a/internal/widget/repository-overview.go b/internal/widget/repository-overview.go index 85a896c..9d4cab3 100644 --- a/internal/widget/repository-overview.go +++ b/internal/widget/repository-overview.go @@ -15,6 +15,7 @@ type Repository struct { Token OptionalEnvString `yaml:"token"` PullRequestsLimit int `yaml:"pull-requests-limit"` IssuesLimit int `yaml:"issues-limit"` + CommitsLimit int `yaml:"commits-limit"` RepositoryDetails feed.RepositoryDetails } @@ -29,6 +30,10 @@ func (widget *Repository) Initialize() error { widget.IssuesLimit = 3 } + if widget.CommitsLimit == 0 || widget.CommitsLimit < -1 { + widget.CommitsLimit = -1 + } + return nil } @@ -38,6 +43,7 @@ func (widget *Repository) Update(ctx context.Context) { string(widget.Token), widget.PullRequestsLimit, widget.IssuesLimit, + widget.CommitsLimit, ) if !widget.canContinueUpdateAfterHandlingErr(err) {