浏览代码

Add last Github commits

Signed-off-by: Anthony Harivel <aharivel@redhat.com>
Anthony Harivel 1 年之前
父节点
当前提交
90d718c186
共有 4 个文件被更改,包括 84 次插入4 次删除
  1. 5 0
      docs/configuration.md
  2. 17 0
      internal/assets/templates/repository.html
  3. 56 4
      internal/feed/github.go
  4. 6 0
      internal/widget/repository-overview.go

+ 5 - 0
docs/configuration.md

@@ -836,6 +836,7 @@ Example:
   repository: glanceapp/glance
   pull-requests-limit: 5
   issues-limit: 3
+  commits-limit: 3
 ```
 
 Preview:
@@ -850,6 +851,7 @@ Preview:
 | token | string | no | |
 | pull-requests-limit | integer | no | 3 |
 | issues-limit | integer | no | 3 |
+| commits-limit | integer | no | 3 |
 
 ##### `repository`
 The owner and repository name that will have their information displayed.
@@ -863,6 +865,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 the lastest commit to show. Set to `-1` to not show any.
+
 ### Bookmarks
 Display a list of links which can be grouped.
 

+ 17 - 0
internal/assets/templates/repository.html

@@ -7,6 +7,23 @@
     <li>{{ .RepositoryDetails.Forks | formatNumber }} forks</li>
 </ul>
 
+{{ if gt (len .RepositoryDetails.Commits) 0 }}
+<hr class="margin-block-10">
+<a class="text-compact" href="https://github.com/{{ $.RepositoryDetails.Name }}/commits" target="_blank" rel="noreferrer">Last {{ .RepositoryDetails.LastCommits | formatNumber }} commits</a>
+<div class="flex gap-7 size-h5 margin-top-3">
+    <ul class="list list-gap-2">
+        {{ range .RepositoryDetails.Commits }}
+        <li title="{{ .Date | formatTime }}" {{ dynamicRelativeTimeAttrs .Date }}>{{ .Date | relativeTime }}</li>
+        {{ end }}
+    </ul>
+    <ul class="list list-gap-2 min-width-0">
+        {{ range .RepositoryDetails.Commits }}
+        <li><a class="color-primary-if-not-visited text-truncate block" title="{{ .Author }}" target="_blank" rel="noreferrer" href="https://github.com/{{ $.RepositoryDetails.Name }}/commits/{{ .Sha }}">{{ .Message }}</a></li>
+        {{ end }}
+    </ul>
+</div>
+{{ end }}
+
 {{ if gt (len .RepositoryDetails.PullRequests) 0 }}
 <hr class="margin-block-10">
 <a class="text-compact" href="https://github.com/{{ $.RepositoryDetails.Name }}/pulls" target="_blank" rel="noreferrer">Open pull requests ({{ .RepositoryDetails.OpenPullRequests | formatNumber }} total)</a>

+ 56 - 4
internal/feed/github.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"log/slog"
 	"net/http"
+	"strings"
 	"sync"
 	"time"
 )
@@ -21,7 +22,6 @@ type githubReleaseResponseJson struct {
 
 func parseGithubTime(t string) time.Time {
 	parsedTime, err := time.Parse("2006-01-02T15:04:05Z", t)
-
 	if err != nil {
 		return time.Now()
 	}
@@ -51,7 +51,6 @@ func FetchLatestReleasesFromGithub(repositories []string, token string) (AppRele
 	task := decodeJsonFromRequestTask[[]githubReleaseResponseJson](defaultClient)
 	job := newJob(task, requests).withWorkers(15)
 	responses, errs, err := workerPoolDo(job)
-
 	if err != nil {
 		return nil, err
 	}
@@ -131,6 +130,8 @@ type RepositoryDetails struct {
 	PullRequests     []GithubTicket
 	OpenIssues       int
 	Issues           []GithubTicket
+	LastCommits      int
+	Commits          []CommitsDetails
 }
 
 type githubRepositoryDetailsResponseJson struct {
@@ -148,21 +149,46 @@ 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 CommitsDetails struct {
+	Sha     string
+	Author  string
+	Email   string
+	Date    time.Time
+	Message string
+}
+
+type Author struct {
+	Name  string `json:"name"`
+	Email string `json:"email"`
+	Date  string `json:"date"`
+}
+
+type Commit struct {
+	Sha    string `json:"sha"`
+	Commit struct {
+		Author  Author `json:"author"`
+		Message string `json:"message"`
+	} `json:"commit"`
+}
 
+type githubCommitsResponseJson []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
@@ -171,6 +197,8 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in
 	var PRsErr error
 	var issuesResponse githubTicketResponseJson
 	var issuesErr error
+	var CommitsResponse githubCommitsResponseJson
+	var CommitsErr error
 	var wg sync.WaitGroup
 
 	wg.Add(1)
@@ -195,6 +223,13 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in
 		})()
 	}
 
+	if maxCommits > 0 {
+		wg.Add(1)
+		go (func() {
+			defer wg.Done()
+			CommitsResponse, CommitsErr = decodeJsonFromRequest[githubCommitsResponseJson](defaultClient, CommitsRequest)
+		})()
+	}
 	wg.Wait()
 
 	if detailsErr != nil {
@@ -207,6 +242,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([]CommitsDetails, 0, len(CommitsResponse)),
 	}
 
 	err = nil
@@ -244,5 +280,21 @@ 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 _, commit := range CommitsResponse {
+				details.LastCommits++
+				details.Commits = append(details.Commits, CommitsDetails{
+					Sha:     commit.Sha,
+					Author:  commit.Commit.Author.Name,
+					Email:   commit.Commit.Author.Email,
+					Date:    parseGithubTime(commit.Commit.Author.Date),
+					Message: strings.SplitN(commit.Commit.Message, "\n\n", 2)[0],
+				})
+			}
+		}
+	}
 	return details, err
 }

+ 6 - 0
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"`
+	CommitsLimits       int               `yaml:"commits-limit"`
 	RepositoryDetails   feed.RepositoryDetails
 }
 
@@ -29,6 +30,10 @@ func (widget *Repository) Initialize() error {
 		widget.IssuesLimit = 3
 	}
 
+	if widget.CommitsLimits == 0 || widget.CommitsLimits < -1 {
+		widget.CommitsLimits = 3
+	}
+
 	return nil
 }
 
@@ -38,6 +43,7 @@ func (widget *Repository) Update(ctx context.Context) {
 		string(widget.Token),
 		widget.PullRequestsLimit,
 		widget.IssuesLimit,
+		widget.CommitsLimits,
 	)
 
 	if !widget.canContinueUpdateAfterHandlingErr(err) {