refactor cli

This commit is contained in:
Daylin Morgan 2024-06-24 14:10:47 -05:00
parent 1077cace3d
commit 91a720541f
Signed by: daylin
GPG key ID: 950D13E9719334AD
13 changed files with 335 additions and 211 deletions

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -12,11 +14,8 @@ var buildCmd = &cobra.Command{
}, },
} }
var minimal bool
func init() { func init() {
rootCmd.AddCommand(buildCmd) rootCmd.AddCommand(buildCmd)
buildCmd.Flags().BoolVar(&nom, "nom", false, "display result with nom") buildCmd.Flags().BoolVar(&nom, "nom", false, "display result with nom")
// buildCmd.Flags().BoolVar(&systemPath, "system-path", false, "build system path derivation")
buildCmd.Flags().BoolVar(&minimal, "minimal", false, "use system dry-run to make build args") buildCmd.Flags().BoolVar(&minimal, "minimal", false, "use system dry-run to make build args")
} }

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -8,10 +10,13 @@ var cacheCmd = &cobra.Command{
Use: "cache", Use: "cache",
Short: "build and push to cachix", Short: "build and push to cachix",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
oizys.SetCache(cacheName)
oizys.CacheBuild(args...) oizys.CacheBuild(args...)
}, },
} }
var cacheName string
func init() { func init() {
cacheCmd.Flags().StringVarP( cacheCmd.Flags().StringVarP(
&cacheName, &cacheName,

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -8,11 +10,11 @@ var dryCmd = &cobra.Command{
Use: "dry", Use: "dry",
Short: "poor man's nix flake check", Short: "poor man's nix flake check",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
oizys.NixDryRun(verbose, args...) oizys.Dry(verbose, minimal, args...)
}, },
} }
func init() { func init() {
rootCmd.AddCommand(dryCmd) rootCmd.AddCommand(dryCmd)
dryCmd.Flags().BoolVarP(&minimal, "minimal", "m", false, "use system dry-run to make build args")
} }

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"oizys/internal/oizys"
) )
var outputCmd = &cobra.Command{ var outputCmd = &cobra.Command{

View file

@ -3,7 +3,7 @@ package cmd
import ( import (
"os" "os"
o "oizys/internal/oizys" "oizys/internal/oizys"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
@ -31,15 +31,13 @@ func Execute() {
var ( var (
flake string flake string
host string host string
cacheName string
verbose bool verbose bool
nom bool nom bool
systemPath bool systemPath bool
resetCache bool resetCache bool
minimal bool
) )
var oizys = o.NewOizys()
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "oizys", Use: "oizys",
Short: "nix begat oizys", Short: "nix begat oizys",
@ -48,7 +46,12 @@ var rootCmd = &cobra.Command{
log.Info("running with verbose mode") log.Info("running with verbose mode")
log.SetLevel(log.DebugLevel) log.SetLevel(log.DebugLevel)
} }
oizys.Set(flake, host, cacheName, verbose, systemPath, resetCache) oizys.SetFlake(flake)
oizys.SetHost(host)
oizys.SetCache(cacheName) // TODO: move
oizys.SetVerbose(verbose)
oizys.SetResetCache(resetCache)
oizys.CheckFlake() oizys.CheckFlake()
}, },
} }

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -1,6 +1,8 @@
package cmd package cmd
import ( import (
"oizys/internal/oizys"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -0,0 +1,48 @@
package oizys
import (
"fmt"
"os"
"os/exec"
"strings"
"time"
"github.com/briandowns/spinner"
"github.com/charmbracelet/log"
)
func logCmd(cmd *exec.Cmd) {
log.Debugf("CMD: %s", strings.Join(cmd.Args, " "))
}
func cmdOutputWithSpinner(cmd *exec.Cmd, msg string, stderr bool) (output []byte, err error) {
logCmd(cmd)
s := startSpinner(msg)
if stderr {
output, err = cmd.CombinedOutput()
} else {
output, err = cmd.Output()
}
s.Stop()
return
}
func startSpinner(msg string) *spinner.Spinner {
s := spinner.New(
spinner.CharSets[14],
100*time.Millisecond,
spinner.WithSuffix(fmt.Sprintf(" %s", msg)),
spinner.WithColor("fgHiMagenta"),
)
s.Start()
return s
}
func exitWithCommand(cmd *exec.Cmd) {
logCmd(cmd)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal("final command failed", "err", err)
}
}

View file

@ -0,0 +1,101 @@
package oizys
import (
"fmt"
"os"
"strings"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
"golang.org/x/term"
)
// TODO: seperate parsing and displaying of packages
func terminalSize() (int, int) {
fd := os.Stdout.Fd()
if !term.IsTerminal(int(fd)) {
log.Error("failed to get terminal size")
return 80, 0
}
w, h, err := term.GetSize(int(fd))
if err != nil {
log.Fatal(err)
}
return w, h
}
type packages struct {
desc string
names []string
pad int
}
func parsePackages(lines []string, desc string) *packages {
w, _ := terminalSize()
maxAcceptable := (w / 4) - 1
maxLen := 0
names := make([]string, len(lines))
for i, pkg := range lines {
s := strings.SplitN(pkg, "-", 2)
if len(s) != 2 {
log.Fatalf("failed to trim hash path from this line: %s\n ", pkg)
}
name := ellipsis(strings.Replace(s[1], ".drv", "", 1), maxAcceptable)
if nameLen := len(name); nameLen > maxLen {
maxLen = nameLen
}
names[i] = name
}
return &packages{names: names, pad: maxLen + 1, desc: desc}
}
func ellipsis(s string, maxLen int) string {
runes := []rune(s)
if len(runes) <= maxLen {
return s
}
if maxLen < 3 {
maxLen = 3
}
return string(runes[0:maxLen-3]) + "..."
}
func (p *packages) show(verbose bool) {
p.summary()
if !verbose || (len(p.names) == 0) {
return
}
pkgs := p.names
w, _ := terminalSize()
nCols := w / p.pad
fmt.Printf("%s\n", strings.Repeat("-", w))
for i, pkg := range pkgs {
fmt.Printf("%-*s", p.pad, pkg)
if (i+1)%nCols == 0 {
fmt.Println()
}
}
fmt.Println()
}
func (p *packages) summary() {
fmt.Printf("%s: %s\n",
p.desc,
lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("6")).
Render(fmt.Sprint(len(p.names))),
)
}
func showFailedOutput(buf []byte) {
arrow := lipgloss.
NewStyle().
Bold(true).
Foreground(lipgloss.Color("9")).
Render("->")
for _, line := range strings.Split(strings.TrimSpace(string(buf)), "\n") {
fmt.Println(arrow, line)
}
}

View file

@ -7,17 +7,20 @@ import (
"io/fs" "io/fs"
"os" "os"
"os/exec" "os/exec"
"sort"
"strings" "strings"
"time"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"golang.org/x/term"
"github.com/briandowns/spinner" "github.com/briandowns/spinner"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
) )
var o *Oizys
func init() {
o = New()
}
// verbose vs debug? // verbose vs debug?
type Oizys struct { type Oizys struct {
flake string flake string
@ -30,12 +33,12 @@ type Oizys struct {
resetCache bool resetCache bool
} }
func NewOizys() *Oizys { func New() *Oizys {
o := new(Oizys) o := new(Oizys)
o.cache = "daylin" o.cache = "daylin"
hostname, err := os.Hostname() hostname, err := os.Hostname()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal("failed to determine hostname", "err", err)
} }
o.host = hostname o.host = hostname
oizysDir, ok := os.LookupEnv("OIZYS_DIR") oizysDir, ok := os.LookupEnv("OIZYS_DIR")
@ -51,6 +54,32 @@ func NewOizys() *Oizys {
return o return o
} }
func SetFlake(path string) {
if path != "" {
o.flake = path
}
}
func SetCache(name string) {
if name != "" {
o.cache = name
}
}
func SetHost(name string) {
if name != "" {
o.host = name
}
}
func SetVerbose(v bool) {
o.verbose = v
}
func SetResetCache(reset bool) {
o.resetCache = reset
}
type Derivation struct { type Derivation struct {
InputDrvs map[string]interface{} InputDrvs map[string]interface{}
} }
@ -68,12 +97,9 @@ func parseSystemPath(derivation map[string]Derivation) (string, error) {
// recreating this command // recreating this command
// nix derivation show `oizys output` | jq -r '.[].inputDrvs | with_entries(select(.key|match("system-path";"i"))) | keys | .[]' // nix derivation show `oizys output` | jq -r '.[].inputDrvs | with_entries(select(.key|match("system-path";"i"))) | keys | .[]'
func (o *Oizys) getSystemPath() string { func getSystemPath() string {
cmd := exec.Command("nix", "derivation", "show", o.nixosConfigAttr()) cmd := exec.Command("nix", "derivation", "show", o.nixosConfigAttr())
logCmd(cmd) out, err := cmdOutputWithSpinner(cmd, "running nix derivation show for full system", false)
s := nixSpinner(o.host)
out, err := cmd.Output()
s.Stop()
if err != nil { if err != nil {
log.Fatal("failed to evalute nixosConfiguration for system-path.drv", "err", err) log.Fatal("failed to evalute nixosConfiguration for system-path.drv", "err", err)
} }
@ -97,117 +123,33 @@ func (o *Oizys) nixosConfigAttr() string {
) )
} }
func (o *Oizys) Output() string { func Output() string {
if o.systemPath { if o.systemPath {
return o.getSystemPath() return getSystemPath()
} else { } else {
return o.nixosConfigAttr() return o.nixosConfigAttr()
} }
} }
func (o *Oizys) Set( // func (o *Oizys) Set(
flake, host, cache string, // flake, host, cache string,
verbose, systemPath, resetCache bool, // verbose, systemPath, resetCache bool,
) { // ) {
if host != "" { // if host != "" {
o.host = host // o.host = host
} // }
if flake != "" { // if flake != "" {
o.flake = flake // o.flake = flake
} // }
if cache != "" { // if cache != "" {
o.cache = cache // o.cache = cache
} // }
o.verbose = verbose // o.verbose = verbose
o.systemPath = systemPath // o.systemPath = systemPath
o.resetCache = resetCache // o.resetCache = resetCache
} // }
// TODO: seperate parsing and displaying of packages func git(rest ...string) *exec.Cmd {
func terminalSize() (int, int) {
fd := os.Stdout.Fd()
if !term.IsTerminal(int(fd)) {
log.Error("failed to get terminal size")
return 80, 0
// log.Fatal("failed to get terminal size")
}
w, h, err := term.GetSize(int(fd))
if err != nil {
log.Fatal(err)
}
return w, h
}
type packages struct {
desc string
names []string
pad int
}
func parsePackages(lines []string, desc string) *packages {
w, _ := terminalSize()
maxAcceptable := (w / 4) - 1
maxLen := 0
names := make([]string, len(lines))
for i, pkg := range lines {
s := strings.SplitN(pkg, "-", 2)
if len(s) != 2 {
log.Fatalf("failed to trim hash path from this line: %s\n ", pkg)
}
name := ellipsis(strings.Replace(s[1], ".drv", "", 1), maxAcceptable)
if nameLen := len(name); nameLen > maxLen {
maxLen = nameLen
}
names[i] = name
}
return &packages{names: names, pad: maxLen + 1, desc: desc}
}
func ellipsis(s string, maxLen int) string {
runes := []rune(s)
if len(runes) <= maxLen {
return s
}
if maxLen < 3 {
maxLen = 3
}
return string(runes[0:maxLen-3]) + "..."
}
func (p *packages) show(verbose bool) {
p.summary()
if !verbose || (len(p.names) == 0) {
return
}
pkgs := p.names
w, _ := terminalSize()
nCols := w / p.pad
fmt.Printf("%s\n", strings.Repeat("-", w))
for i, pkg := range pkgs {
fmt.Printf("%-*s", p.pad, pkg)
if (i+1)%nCols == 0 {
fmt.Println()
}
}
fmt.Println()
}
func (p *packages) summary() {
fmt.Printf("%s: %s\n",
p.desc,
lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("6")).
Render(fmt.Sprint(len(p.names))),
)
}
func logCmd(cmd *exec.Cmd) {
log.Debugf("CMD: %s", strings.Join(cmd.Args, " "))
}
func (o *Oizys) git(rest ...string) *exec.Cmd {
args := []string{"-C", o.flake} args := []string{"-C", o.flake}
args = append(args, rest...) args = append(args, rest...)
cmd := exec.Command("git", args...) cmd := exec.Command("git", args...)
@ -215,19 +157,8 @@ func (o *Oizys) git(rest ...string) *exec.Cmd {
return cmd return cmd
} }
func showFailedOutput(buf []byte) { func GitPull() {
arrow := lipgloss. cmdOutput, err := git("status", "--porcelain").Output()
NewStyle().
Bold(true).
Foreground(lipgloss.Color("9")).
Render("->")
for _, line := range strings.Split(strings.TrimSpace(string(buf)), "\n") {
fmt.Println(arrow, line)
}
}
func (o *Oizys) GitPull() {
cmdOutput, err := o.git("status", "--porcelain").Output()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -238,7 +169,7 @@ func (o *Oizys) GitPull() {
os.Exit(1) os.Exit(1)
} }
cmdOutput, err = o.git("pull").CombinedOutput() cmdOutput, err = git("pull").CombinedOutput()
if err != nil { if err != nil {
showFailedOutput(cmdOutput) showFailedOutput(cmdOutput)
log.Fatal(err) log.Fatal(err)
@ -301,24 +232,38 @@ func showDryRunResult(nixOutput string, verbose bool) {
toFetch.show(verbose) toFetch.show(verbose)
} }
func (o *Oizys) NixDryRun(verbose bool, rest ...string) { func Dry(verbose bool, minimal bool, rest ...string) {
args := []string{ cmd := exec.Command("nix", "build", "--dry-run")
"build", o.nixosConfigAttr(), "--dry-run", cmd.Args = append(cmd.Args, rest...)
var spinnerMsg string
if minimal {
drvs := systemPathDrvsToBuild()
if len(drvs) == 0 {
log.Info("no packages in minimal set to build")
os.Exit(0)
} }
args = append(args, rest...) cmd.Args = append(cmd.Args, drvs...)
cmd := exec.Command("nix", args...) spinnerMsg = "evaluting for minimal build needs"
s := nixSpinner(o.host) } else {
result, err := cmd.CombinedOutput() log.Debug("evalutating full nixosConfiguration")
s.Stop() cmd.Args = append(cmd.Args, o.nixosConfigAttr())
spinnerMsg = fmt.Sprintf("%s %s", "evaluating derivation for:",
lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("6")).Render(o.host),
)
}
result, err := cmdOutputWithSpinner(cmd, spinnerMsg, true)
if err != nil { if err != nil {
fmt.Println(string(result)) log.Fatal("failed to dry-run nix build", "err", err, "output", string(result))
log.Fatal(err)
} }
if minimal {
fmt.Println(string(result))
} else {
showDryRunResult(string(result), verbose) showDryRunResult(string(result), verbose)
} }
}
// / Setup command completely differently here // / Setup command completely differently here
func (o *Oizys) NixosRebuild(subcmd string, rest ...string) { func NixosRebuild(subcmd string, rest ...string) {
cmd := exec.Command("sudo", cmd := exec.Command("sudo",
"nixos-rebuild", "nixos-rebuild",
subcmd, subcmd,
@ -329,19 +274,10 @@ func (o *Oizys) NixosRebuild(subcmd string, rest ...string) {
if o.verbose { if o.verbose {
cmd.Args = append(cmd.Args, "--print-build-logs") cmd.Args = append(cmd.Args, "--print-build-logs")
} }
runCommand(cmd) exitWithCommand(cmd)
} }
func runCommand(cmd *exec.Cmd) { func NixBuild(nom bool, minimal bool, rest ...string) {
logCmd(cmd)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
func (o *Oizys) NixBuild(nom bool, minimal bool, rest ...string) {
var cmdName string var cmdName string
if nom { if nom {
cmdName = "nom" cmdName = "nom"
@ -349,7 +285,6 @@ func (o *Oizys) NixBuild(nom bool, minimal bool, rest ...string) {
cmdName = "nix" cmdName = "nix"
} }
cmd := exec.Command(cmdName, "build") cmd := exec.Command(cmdName, "build")
cmd.Args = append(cmd.Args, rest...) cmd.Args = append(cmd.Args, rest...)
if o.resetCache { if o.resetCache {
cmd.Args = append(cmd.Args, "--narinfo-cache-positive-ttl", "0") cmd.Args = append(cmd.Args, "--narinfo-cache-positive-ttl", "0")
@ -359,7 +294,7 @@ func (o *Oizys) NixBuild(nom bool, minimal bool, rest ...string) {
// } // }
if minimal { if minimal {
log.Debug("populating args with derivations not already built") log.Debug("populating args with derivations not already built")
drvs := o.systemPathDrvsToBuild() drvs := systemPathDrvsToBuild()
if len(drvs) == 0 { if len(drvs) == 0 {
log.Info("nothing to build. exiting...") log.Info("nothing to build. exiting...")
os.Exit(0) os.Exit(0)
@ -367,7 +302,7 @@ func (o *Oizys) NixBuild(nom bool, minimal bool, rest ...string) {
cmd.Args = append(cmd.Args, drvs...) cmd.Args = append(cmd.Args, drvs...)
} }
runCommand(cmd) exitWithCommand(cmd)
} }
var ignoredMap = stringSliceToMap( var ignoredMap = stringSliceToMap(
@ -395,10 +330,10 @@ var ignoredMap = stringSliceToMap(
}, },
) )
func drvIsIgnored(drv string) bool { func drvNotIgnored(drv string) bool {
s := strings.SplitN(strings.Replace(drv, ".drv", "", 1), "-", 2) s := strings.SplitN(strings.Replace(drv, ".drv", "", 1), "-", 2)
_, ok := ignoredMap[s[len(s)-1]] _, ok := ignoredMap[s[len(s)-1]]
return ok return !ok
} }
func stringSliceToMap(slice []string) map[string]struct{} { func stringSliceToMap(slice []string) map[string]struct{} {
@ -419,41 +354,72 @@ func drvsToInputs(derivation map[string]Derivation) []string {
return drvs return drvs
} }
// v2 // compute the overlap between two slices of strings
func (o *Oizys) systemPathDrvsToBuild() []string { func overlapStrings(a []string, b []string) []string {
log.Debug("getting system-path build-only deps") var overlap []string
systemPathDrv := fmt.Sprintf("%s^*", o.getSystemPath()) set := stringSliceToMap(a)
derivationCmd := exec.Command("nix", "derivation", "show", systemPathDrv) for _, s := range b {
logCmd(derivationCmd) _, ok := set[s]
output, err := derivationCmd.Output() if ok {
if err != nil { overlap = append(overlap, s)
log.Fatal("failed to evaluate", "drv", systemPathDrv) }
}
return overlap
} }
// TODO: abstract this? func nixDerivationShowToInputs(output []byte) []string {
var derivation map[string]Derivation var derivation map[string]Derivation
if err := json.Unmarshal(output, &derivation); err != nil { if err := json.Unmarshal(output, &derivation); err != nil {
log.Fatal(err) log.Fatal(err)
} }
systemPathInputDrvs := stringSliceToMap(drvsToInputs(derivation)) return drvsToInputs(derivation)
}
// get to build packages for full system func filter[T any](ss []T, test func(T) bool) (ret []T) {
for _, s := range ss {
if test(s) {
ret = append(ret, s)
}
}
return
}
func toBuildNixosConfiguration() []string {
systemCmd := exec.Command("nix", "build", o.nixosConfigAttr(), "--dry-run") systemCmd := exec.Command("nix", "build", o.nixosConfigAttr(), "--dry-run")
logCmd(systemCmd) result, err := cmdOutputWithSpinner(
result, err := systemCmd.CombinedOutput() systemCmd,
fmt.Sprintf("running dry build for: %s", o.nixosConfigAttr()),
true,
)
if err != nil { if err != nil {
log.Fatal("failed to dry-run build full system", "err", err) log.Fatal("failed to dry-run build system", "err", err)
} }
toBuild, _ := parseDryRun2(string(result)) toBuild, _ := parseDryRun2(string(result))
return toBuild
}
var toActuallyBuild []string func systemPathDerivationShow() []string {
for _, drv := range toBuild { systemPathDrv := fmt.Sprintf("%s^*", getSystemPath())
_, ok := systemPathInputDrvs[drv] derivationCmd := exec.Command("nix", "derivation", "show", systemPathDrv)
if ok && !drvIsIgnored(drv) { output, err := cmdOutputWithSpinner(
toActuallyBuild = append(toActuallyBuild, drv) derivationCmd,
fmt.Sprintf("evaluating system path: %s", systemPathDrv),
false)
if err != nil {
log.Fatal("failed to evaluate", "drv", systemPathDrv)
} }
return nixDerivationShowToInputs(output)
} }
func systemPathDrvsToBuild() []string {
toBuild := toBuildNixosConfiguration()
systemPathInputDrvs := systemPathDerivationShow()
toActuallyBuild := filter(
overlapStrings(systemPathInputDrvs, toBuild),
drvNotIgnored,
)
drvs := make([]string, len(toActuallyBuild)) drvs := make([]string, len(toActuallyBuild))
for i, pkg := range toActuallyBuild { for i, pkg := range toActuallyBuild {
drvs[i] = fmt.Sprintf("%s^*", strings.TrimSpace(pkg)) drvs[i] = fmt.Sprintf("%s^*", strings.TrimSpace(pkg))
@ -461,11 +427,6 @@ func (o *Oizys) systemPathDrvsToBuild() []string {
return drvs return drvs
} }
func contains(s []string, search string) bool {
i := sort.SearchStrings(s, search)
return i < len(s) && s[i] == search
}
func (o *Oizys) writeToGithubStepSummary(txt string) { func (o *Oizys) writeToGithubStepSummary(txt string) {
f, err := os.OpenFile(o.githubSummary, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) f, err := os.OpenFile(o.githubSummary, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil { if err != nil {
@ -513,14 +474,14 @@ func (o *Oizys) checkPath(name string) string {
return fmt.Sprintf("%s#checks.x86_64-linux.%s", o.flake, name) return fmt.Sprintf("%s#checks.x86_64-linux.%s", o.flake, name)
} }
func (o *Oizys) Checks(nom bool, rest ...string) { func Checks(nom bool, rest ...string) {
checks := o.getChecks() checks := o.getChecks()
for _, check := range checks { for _, check := range checks {
o.NixBuild(nom, false, o.checkPath(check)) NixBuild(nom, false, o.checkPath(check))
} }
} }
func (o *Oizys) CacheBuild(rest ...string) { func CacheBuild(rest ...string) {
args := []string{ args := []string{
"watch-exec", o.cache, "--", "nix", "watch-exec", o.cache, "--", "nix",
"build", o.nixosConfigAttr(), "--print-build-logs", "build", o.nixosConfigAttr(), "--print-build-logs",
@ -528,10 +489,10 @@ func (o *Oizys) CacheBuild(rest ...string) {
} }
args = append(args, rest...) args = append(args, rest...)
cmd := exec.Command("cachix", args...) cmd := exec.Command("cachix", args...)
runCommand(cmd) exitWithCommand(cmd)
} }
func (o *Oizys) CheckFlake() { func CheckFlake() {
if _, ok := os.LookupEnv("OIZYS_SKIP_CHECK"); !ok { if _, ok := os.LookupEnv("OIZYS_SKIP_CHECK"); !ok {
if _, err := os.Stat(o.flake); errors.Is(err, fs.ErrNotExist) { if _, err := os.Stat(o.flake); errors.Is(err, fs.ErrNotExist) {
log.Fatalf("path to flake: %s does not exist", o.flake) log.Fatalf("path to flake: %s does not exist", o.flake)
@ -539,23 +500,17 @@ func (o *Oizys) CheckFlake() {
} }
} }
func (o *Oizys) CI(rest ...string) { func CI(rest ...string) {
args := []string{"workflow", "run", "build.yml", "-F", fmt.Sprintf("hosts=%s", o.host)} args := []string{"workflow", "run", "build.yml", "-F", fmt.Sprintf("hosts=%s", o.host)}
args = append(args, rest...) args = append(args, rest...)
cmd := exec.Command("gh", args...) cmd := exec.Command("gh", args...)
runCommand(cmd) exitWithCommand(cmd)
} }
// TODO: deprecate
func nixSpinner(host string) *spinner.Spinner { func nixSpinner(host string) *spinner.Spinner {
msg := fmt.Sprintf("%s %s", " evaluating derivation for:", msg := fmt.Sprintf("%s %s", " evaluating derivation for:",
lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("6")).Render(host), lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("6")).Render(host),
) )
s := spinner.New( return startSpinner(msg)
spinner.CharSets[14],
100*time.Millisecond,
spinner.WithSuffix(msg),
spinner.WithColor("fgHiMagenta"),
)
s.Start()
return s
} }