53 lines
2.1 KiB
Go
53 lines
2.1 KiB
Go
package buildstep
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// Guard is a build module's check that the toolchain installed on its node is the one its recipe builds with
|
|
// (novox/hq ADR 0469 §1; issue 1473). The same guard serves ADR 0470 §4's postgres major for the integration
|
|
// level, with its own Probe and Want.
|
|
type Guard struct {
|
|
// Language is the toolchain's key part: go or typescript (delivery.ToolchainKey).
|
|
Language string
|
|
// Want is the toolchain version the recipe builds with, and Recipe the recipe's own version. The indexer
|
|
// compares both texts as they are written here.
|
|
Want, Recipe string
|
|
// Probe reads the installed version (go version, node --version).
|
|
Probe func(ctx context.Context) (installed string, err error)
|
|
Node string
|
|
// Put is the toolchains state's Put (stdio.State(delivery.ToolchainsState).Put).
|
|
Put Put
|
|
}
|
|
|
|
// Check probes the installed version, writes it to <node>.<language> of the toolchains state every time it runs,
|
|
// and answers nil when it is the recipe's. Otherwise it answers a *Refusal naming both versions; the installed
|
|
// version is written even then, so the indexer sees that builders disagree. A probe that fails is a *Refusal
|
|
// naming its failure, and nothing is written. A write that fails is an error that is not a Refusal.
|
|
func (g Guard) Check(ctx context.Context) error {
|
|
installed, err := g.Probe(ctx)
|
|
if err != nil {
|
|
return &Refusal{Text: fmt.Sprintf("the installed %s version could not be read: %v", g.Language, err), Want: g.Want}
|
|
}
|
|
key, err := delivery.ToolchainKey(g.Node, g.Language)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
raw, err := delivery.EncodeToolchain(delivery.Toolchain{Language: g.Language, Version: installed, Recipe: g.Recipe, At: now().UTC()})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := g.Put(key, json.RawMessage(raw)); err != nil {
|
|
return fmt.Errorf("buildstep: writing the toolchain %s: %w", key, err)
|
|
}
|
|
if installed != g.Want {
|
|
return &Refusal{Text: fmt.Sprintf("%s %s installed, the recipe builds with %s %s", g.Language, installed, g.Language, g.Want),
|
|
Want: g.Want, Have: installed}
|
|
}
|
|
return nil
|
|
}
|