70 lines
2.7 KiB
Go
70 lines
2.7 KiB
Go
// repositories: the organisation's repositories from the gitea module's config value `repositories` (novox/hq
|
|
// ADR 0428, issue 1124). `repositories sync` is a run-once process the node-engine runs when the module starts and
|
|
// again whenever the value changes: it reads the file the mesh renders from that value and, with the setup login,
|
|
// makes every listed repository that does not exist under that login's own account, protects its main, writes
|
|
// main's first commit, narrows main's rule and only then moves it into the organisation; one that exists only has
|
|
// its main rule put right. A repository the value does not list is never touched. It keeps what it did, per
|
|
// repository, in the outcome file, says each change on stdout in one line and never a secret, and exits 1 when a
|
|
// step was refused, its last stderr lines naming each (outcome.go Report): the node-engine's gate on a run-once
|
|
// step (ADR 0136) reports it and runs it again on every apply until it passes.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"gitea/internal/forgehttp"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) != 2 || os.Args[1] != "sync" {
|
|
fmt.Fprintln(os.Stderr, "usage: repositories sync")
|
|
os.Exit(2)
|
|
}
|
|
os.Exit(runSync())
|
|
}
|
|
|
|
func runSync() int {
|
|
forge, missing := forgehttp.FromEnv()
|
|
file, outcome := os.Getenv("MESH_REPOSITORIES_FILE"), os.Getenv("MESH_REPOSITORIES_OUTCOME")
|
|
for k, v := range map[string]string{"MESH_REPOSITORIES_FILE": file, "MESH_REPOSITORIES_OUTCOME": outcome} {
|
|
if v == "" {
|
|
missing = append(missing, k)
|
|
}
|
|
}
|
|
if forge.TokenFile != "" {
|
|
// The tools' account cannot make or protect a repository, and must not (ADR 0428 §8).
|
|
missing = append(missing, "the setup login (MESH_GITEA_TOKEN_FILE is set instead)")
|
|
}
|
|
if len(missing) > 0 {
|
|
fmt.Fprintf(os.Stderr, "repositories: %v not set by the manifest; nothing was changed\n", missing)
|
|
return 1
|
|
}
|
|
toolsAccount := os.Getenv("MESH_GITEA_TOOLS_USER")
|
|
if toolsAccount == "" {
|
|
toolsAccount = forgehttp.ToolsAccount
|
|
}
|
|
s := &Syncer{Forge: forge, Org: "novox", Admin: forge.User, Tools: toolsAccount,
|
|
Log: func(format string, a ...any) { fmt.Printf(format+"\n", a...) },
|
|
WaitFor: 3 * time.Minute, Poll: 5 * time.Second}
|
|
value, err := ReadValue(file)
|
|
if err != nil {
|
|
o := Outcome{At: time.Now().UTC(), Org: s.Org, Failed: err.Error()}
|
|
_ = WriteOutcome(outcome, o)
|
|
return Report(o, os.Stderr)
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
|
defer cancel()
|
|
o, _ := s.Sync(ctx, value) // a forge not reachable is in o.Failed
|
|
werr := WriteOutcome(outcome, o)
|
|
if werr != nil {
|
|
fmt.Fprintln(os.Stderr, "repositories: the outcome could not be kept:", werr)
|
|
}
|
|
if code := Report(o, os.Stderr); code != 0 || werr == nil {
|
|
return code
|
|
}
|
|
return 1
|
|
}
|