Files
mesh-catalog/modules/gitea/cmd/repositories/outcome.go
T

80 lines
2.4 KiB
Go

package main
// What a pass left (ADR 0428 §6): the outcome file, and the pass's exit. A refused step is not judged by a health
// check of its own: the sync is a run-once process, so its non-zero exit is the node-engine's gate (ADR 0136). The
// module's step is reported failed, apply-failing is raised, and every apply runs it again until it passes, which is
// the "next pass" of §6. Its last stderr lines name each refused repository, its step and the forge's answer.
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// WriteOutcome keeps what the pass did per repository, whole or not at all.
func WriteOutcome(file string, o Outcome) error {
raw, err := json.MarshalIndent(o, "", " ")
if err != nil {
return err
}
tmp, err := os.CreateTemp(filepath.Dir(file), ".repositories-*")
if err != nil {
return err
}
defer os.Remove(tmp.Name())
if _, err := tmp.Write(append(raw, '\n')); err != nil {
tmp.Close()
return err
}
if err := tmp.Chmod(0o644); err != nil {
tmp.Close()
return err
}
if err := tmp.Close(); err != nil {
return err
}
return os.Rename(tmp.Name(), file)
}
// ReadOutcome reads what the last pass left.
func ReadOutcome(file string) (*Outcome, error) {
raw, err := os.ReadFile(file)
if err != nil {
return nil, err
}
var o Outcome
if err := json.Unmarshal(raw, &o); err != nil {
return nil, fmt.Errorf("the outcome %s is not readable: %w", file, err)
}
return &o, nil
}
// Report says on stderr what the pass refused and is the pass's exit: 0 when every listed repository was made, put
// right or already right; 1 otherwise. One line per refused repository, "repositories: <name>: <step> refused:
// <forge answer>", then a summary line, so the line the node-engine keeps last names what to look at.
func Report(o Outcome, stderr io.Writer) int {
if o.Failed != "" {
fmt.Fprintf(stderr, "repositories: the pass did not run: %s; nothing was made\n", o.Failed)
return 1
}
refused := o.Refused()
if len(refused) == 0 {
return 0
}
for _, r := range refused {
fmt.Fprintf(stderr, "repositories: %s: %s refused: %s\n", r.Name, r.Step, r.Said)
}
if len(refused) > 1 {
names := make([]string, 0, len(refused))
for _, r := range refused {
names = append(names, r.Name)
}
fmt.Fprintf(stderr, "repositories: %d of %d repositories had a step refused (%s); nothing further of them was done, the rest were\n",
len(refused), len(o.Repositories), strings.Join(names, ", "))
}
return 1
}