Timetracking Jobs
This commit is contained in:
146
scripts/timetracking/main.go
Normal file
146
scripts/timetracking/main.go
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/sdk/gitea"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
url := os.Getenv("GITEA_URL")
|
||||||
|
token := os.Getenv("GITEA_TOKEN")
|
||||||
|
repoFullName := os.Getenv("GITEA_REPO") // format: owner/repo
|
||||||
|
orgName := os.Getenv("GITEA_ORG")
|
||||||
|
|
||||||
|
if url == "" || token == "" {
|
||||||
|
log.Fatal("Missing required environment variables: GITEA_URL, GITEA_TOKEN")
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoFullName == "" && orgName == "" {
|
||||||
|
log.Fatal("Either GITEA_REPO or GITEA_ORG must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.NewClient(url, gitea.SetToken(token))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to create Gitea client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var repos []*gitea.Repository
|
||||||
|
if orgName != "" {
|
||||||
|
fmt.Printf("Fetching all repositories for organization: %s\n", orgName)
|
||||||
|
page := 1
|
||||||
|
for {
|
||||||
|
orgRepos, _, err := client.ListOrgRepos(orgName, gitea.ListOrgReposOptions{
|
||||||
|
ListOptions: gitea.ListOptions{Page: page, PageSize: 50},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to fetch organization repositories: %v", err)
|
||||||
|
}
|
||||||
|
if len(orgRepos) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
repos = append(repos, orgRepos...)
|
||||||
|
page++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parts := strings.Split(repoFullName, "/")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
log.Fatal("GITEA_REPO must be in format 'owner/repo'")
|
||||||
|
}
|
||||||
|
repo, _, err := client.GetRepo(parts[0], parts[1])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to fetch repository: %v", err)
|
||||||
|
}
|
||||||
|
repos = append(repos, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start date for Sprint 1 (2024-10-02)
|
||||||
|
startDate := time.Date(2025, 5, 2, 0, 0, 0, 0, time.Local)
|
||||||
|
|
||||||
|
// user -> bucketIndex -> hours
|
||||||
|
data := make(map[string]map[int]float64)
|
||||||
|
maxBucket := 0
|
||||||
|
|
||||||
|
for _, r := range repos {
|
||||||
|
fmt.Printf("Processing repository: %s/%s\n", r.Owner.UserName, r.Name)
|
||||||
|
page := 1
|
||||||
|
for {
|
||||||
|
times, _, err := client.ListRepoTrackedTimes(r.Owner.UserName, r.Name, gitea.ListTrackedTimesOptions{
|
||||||
|
ListOptions: gitea.ListOptions{Page: page, PageSize: 50},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Warning: Failed to fetch time tracking for %s (page %d): %v\n", r.Name, page, err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if len(times) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range times {
|
||||||
|
if t.Created.Before(startDate) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
daysSinceStart := int(t.Created.Sub(startDate).Hours() / 24)
|
||||||
|
bucketIndex := daysSinceStart / 14
|
||||||
|
if bucketIndex < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if bucketIndex > maxBucket {
|
||||||
|
maxBucket = bucketIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
userName := t.UserName
|
||||||
|
if data[userName] == nil {
|
||||||
|
data[userName] = make(map[int]float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
hours := float64(t.Time) / 3600.0
|
||||||
|
data[userName][bucketIndex] += hours
|
||||||
|
}
|
||||||
|
page++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
fmt.Println("No time tracking entries found.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print Table
|
||||||
|
users := make([]string, 0, len(data))
|
||||||
|
for u := range data {
|
||||||
|
users = append(users, u)
|
||||||
|
}
|
||||||
|
sort.Strings(users)
|
||||||
|
|
||||||
|
// Header
|
||||||
|
fmt.Print("\nNutzer ")
|
||||||
|
for i := 0; i <= maxBucket; i++ {
|
||||||
|
start := startDate.AddDate(0, 0, i*14)
|
||||||
|
fmt.Printf("| %s ", start.Format("02.01."))
|
||||||
|
}
|
||||||
|
fmt.Println("| Gesamt")
|
||||||
|
fmt.Println(strings.Repeat("-", 14+(maxBucket+1)*10+8))
|
||||||
|
|
||||||
|
for _, u := range users {
|
||||||
|
fmt.Printf("%-12s ", u)
|
||||||
|
total := 0.0
|
||||||
|
for i := 0; i <= maxBucket; i++ {
|
||||||
|
h := data[u][i]
|
||||||
|
total += h
|
||||||
|
if h > 0 {
|
||||||
|
fmt.Printf("| %7.1fh ", h)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("| %8s ", "-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("| %7.1fh\n", total)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user