soc/intel/cmn/cse: Deprecate CONFIG_SOC_INTEL_CSE_RW_VERSION
[coreboot2.git] / util / docker / coreboot.org-status / board-status.html / logs.go
blob21e91f2d9ab3d98ef435da993220ee25955f7aed
1 package main
3 import (
4 "fmt"
5 "io/fs"
6 "os"
7 "os/exec"
8 "path/filepath"
9 "sort"
10 "strings"
11 "time"
14 // Color returns a HTML color code between green and yellow based on the
15 // number of days that passed since ds.
16 func (ds DateString) Color() string {
17 date, _ := time.Parse("2006-01-02T15:04:05Z", string(ds))
18 days := int(time.Since(date).Hours() / 24)
19 if days > 255 {
20 days = 255
22 return fmt.Sprintf("#%02xff00", days)
25 func fetchLogs(dirs chan<- NamedFS) {
26 err := fs.WalkDir(bsdirFS, ".", func(path string, d fs.DirEntry, err error) error {
27 if err != nil {
28 return err
30 if path[0] == '.' {
31 return nil
33 if d.IsDir() && len(strings.Split(path, string(filepath.Separator))) == 4 {
34 dirs <- NamedFS{
35 FS: bsdirFS,
36 Name: path,
39 return nil
41 if err != nil {
42 fmt.Fprintf(os.Stderr, "Reading logs failed: %v\n", err)
44 close(dirs)
47 func collectLogs(dirs <-chan NamedFS) {
48 data.Logs = make(map[Timeframe][]Log)
49 data.VendorBoardDate = make(map[string]DateString)
50 data.VendorBoardReferenced = make(map[string]bool)
51 timeframes := make(map[Timeframe]bool)
52 gitcache := make(map[string]string)
53 for dir := range dirs {
54 upstream := ""
55 revB, err := fs.ReadFile(dir.FS, filepath.Join(dir.Name, "revision.txt"))
56 if err != nil {
57 continue
59 rev := string(revB)
60 skipDir := false
61 for _, line := range strings.Split(rev, "\n") {
62 item := strings.SplitN(line, ":", 2)
63 if len(item) != 2 {
64 // This is an error, but let's try to extract
65 // as much value out of revision.txt files as
66 // possible, even if some lines are erroneous.
67 continue
69 if item[0] == "Upstream revision" {
70 upstream = strings.TrimSpace(item[1])
71 // tried using go-git, but its resolver
72 // couldn't expand short hashes despite the
73 // docs claiming that it can.
74 if val, ok := gitcache[upstream]; ok {
75 upstream = val
76 } else {
77 res, err := exec.Command("/usr/bin/git", "-C", cbdir, "log", "-n1", "--format=%H", upstream).Output()
78 if err != nil {
79 fmt.Fprintf(os.Stderr, "revision %s not found \n", upstream)
80 skipDir = true
81 break
83 gitcache[upstream] = strings.TrimSpace(string(res))
84 upstream = gitcache[upstream]
88 if skipDir {
89 continue
92 rawFiles, err := fs.Glob(dir.FS, filepath.Join(dir.Name, "*"))
93 if err != nil {
94 fmt.Fprintf(os.Stderr, "Could not fetch log data, skipping: %v\n", err)
95 continue
98 pieces := strings.Split(dir.Name, string(filepath.Separator))
99 if len(pieces) < 4 {
100 fmt.Fprintf(os.Stderr, "log directory %s is malformed, skipping\n", dir.Name)
101 continue
103 vendorBoard := strings.Join(pieces[:2], "/")
104 // TODO: these need to become "second to last" and "last" item
105 // but only after compatibility to the current system has been ensured.
106 dateTimePath := pieces[3]
107 dateTime, err := time.Parse(time.RFC3339, strings.ReplaceAll(dateTimePath, "_", ":"))
108 if err != nil {
109 fmt.Fprintf(os.Stderr, "Could not parse timestamp from %s: %v\n", dir.Name, err)
110 continue
112 dateTimeNormal := dateTime.UTC().Format("2006-01-02T15:04:05Z")
113 dateTimeHuman := dateTime.UTC().Format(time.UnixDate)
114 tfYear, tfWeek := dateTime.ISOWeek()
115 timeframe := Timeframe(fmt.Sprintf("%dW%02d", tfYear, tfWeek))
117 if !timeframes[timeframe] {
118 timeframes[timeframe] = true
119 data.Timeframes = append(data.Timeframes, timeframe)
120 data.Logs[timeframe] = []Log{}
123 files := []Path{}
124 l := len(dir.Name) + 1
125 for _, file := range rawFiles {
126 if file[l:] == "revision.txt" {
127 continue
129 files = append(files, Path{
130 Path: dir.Name + "/",
131 Basename: file[l:],
135 data.Logs[timeframe] = append(data.Logs[timeframe], Log{
136 VendorBoard: vendorBoard,
137 Time: dateTimeNormal,
138 TimeReadable: dateTimeHuman,
139 Upstream: upstream,
140 Files: files,
143 sort.Slice(data.Timeframes, func(i, j int) bool {
144 // reverse sort
145 return data.Timeframes[i] > data.Timeframes[j]
147 for bi := range data.Logs {
148 bucket := data.Logs[bi]
149 sort.Slice(data.Logs[bi], func(i, j int) bool {
150 if bucket[i].Time == bucket[j].Time {
151 return (bucket[i].VendorBoard > bucket[j].VendorBoard)
153 return (bucket[i].Time > bucket[j].Time)
156 for _, ts := range data.Timeframes {
157 for li, l := range data.Logs[ts] {
158 if _, match := data.VendorBoardDate[l.VendorBoard]; match {
159 continue
161 data.VendorBoardDate[l.VendorBoard] = DateString(l.Time)
162 data.Logs[ts][li].Reference = true