Files
bootstrap_windows_env/internal/bootstrap/runlog.go
T

114 lines
2.8 KiB
Go

package bootstrap
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
)
type RunReport struct {
Started time.Time
Finished time.Time
Options Options
Phases []Phase
Events []string
Notices []string
Issues Issues
FinalError string
}
func NewRunReport(opts Options, phases []Phase) *RunReport {
return &RunReport{
Started: time.Now(),
Options: opts,
Phases: append([]Phase(nil), phases...),
}
}
func (r *RunReport) Event(format string, args ...any) {
r.Events = append(r.Events, fmt.Sprintf(format, args...))
}
func (r *RunReport) Notice(notice string) {
r.Notices = append(r.Notices, notice)
r.Event("notice: %s", notice)
}
func (r *RunReport) Issue(issue Issue) {
r.Issues = append(r.Issues, issue)
r.Event("error: %s: %v", issue.Step, issue.Err)
}
func (r *RunReport) Finish(err error) {
r.Finished = time.Now()
if err != nil {
r.FinalError = err.Error()
}
}
func WriteRunLog(paths UserPaths, report *RunReport) (string, error) {
documents := paths.Documents
if documents == "" {
return "", fmt.Errorf("documents path is empty")
}
if err := os.MkdirAll(documents, 0o755); err != nil {
return "", err
}
name := "bootstrap_windows_env-" + report.Started.Format("20060102-150405") + ".log"
path := filepath.Join(documents, name)
var b strings.Builder
fmt.Fprintf(&b, "bootstrap_windows_env run\n")
fmt.Fprintf(&b, "started: %s\n", report.Started.Format(time.RFC3339))
if !report.Finished.IsZero() {
fmt.Fprintf(&b, "finished: %s\n", report.Finished.Format(time.RFC3339))
fmt.Fprintf(&b, "duration: %s\n", report.Finished.Sub(report.Started).Round(time.Second))
}
fmt.Fprintf(&b, "phases: %s\n", phasesForLog(report.Phases))
fmt.Fprintf(&b, "options: only=%s no-ai=%t no-wsl=%t yes=%t dry-run=%t linux-release-repo=%s\n",
report.Options.Only,
report.Options.NoAI,
report.Options.NoWSL,
report.Options.Yes,
report.Options.DryRun,
report.Options.LinuxReleaseRepo,
)
if report.FinalError != "" {
fmt.Fprintf(&b, "result: failed\n")
fmt.Fprintf(&b, "error: %s\n", report.FinalError)
} else {
fmt.Fprintf(&b, "result: completed\n")
}
if len(report.Events) > 0 {
fmt.Fprintf(&b, "\nevents:\n")
for _, event := range report.Events {
fmt.Fprintf(&b, "- %s\n", event)
}
}
if len(report.Notices) > 0 {
fmt.Fprintf(&b, "\nnotices:\n")
for _, notice := range report.Notices {
fmt.Fprintf(&b, "- %s\n", notice)
}
}
if len(report.Issues) > 0 {
fmt.Fprintf(&b, "\nerrors:\n")
for _, issue := range report.Issues {
fmt.Fprintf(&b, "- %s: %v\n", issue.Step, issue.Err)
}
}
if err := os.WriteFile(path, []byte(b.String()), 0o644); err != nil {
return "", err
}
return path, nil
}
func phasesForLog(phases []Phase) string {
parts := make([]string, 0, len(phases))
for _, phase := range phases {
parts = append(parts, string(phase))
}
return strings.Join(parts, ",")
}