Timetracking Jobs

This commit is contained in:
2026-03-20 21:49:31 +01:00
parent e7f38c88bf
commit 79203e5c5b

View 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)
}
}