oizys/pkgs/oizys-nim/oizys.nim

198 lines
4.8 KiB
Nim
Raw Normal View History

2024-03-14 10:44:57 -05:00
import std/[macros, os, osproc, parseopt, times, strformat, strutils, terminal]
2024-01-28 11:00:05 -06:00
from std/nativesockets import getHostname
let summaryFile = getEnv("GITHUB_STEP_SUMMARY")
2024-03-14 10:44:57 -05:00
macro doc(procedure: typed): untyped =
## extract documenatation comments from procedure
procedure.expectKind(nnkSym)
if procedure.symKind != nskProc:
error("procedure expected", procedure)
let
impl = procedure.getImpl
docs = impl.body.extractDocCommentsAndRunnables
var doc: string
for element in docs:
if element.kind == nnkCommentStmt:
doc.addSep("\n", startLen = 1)
doc.add($element)
result = newLit(doc)
proc logInfo(args: varargs[string, `$`]) =
2024-01-28 12:08:38 -06:00
stdout.styledWriteLine(
fgCyan, "oizys", resetStyle, "|",
styleDim, "INFO", resetStyle, "| ",
args.join("")
)
2024-03-14 10:44:57 -05:00
proc logErr(args: varargs[string, `$`]) =
2024-01-28 12:08:38 -06:00
stdout.styledWriteLine(
fgCyan, "oizys", resetStyle, "|",
2024-01-29 10:31:18 -06:00
fgRed, "ERROR", resetStyle, "| ",
2024-01-28 12:08:38 -06:00
args.join("")
)
2024-03-14 10:44:57 -05:00
proc logWarn(args: varargs[string, `$`]) =
2024-03-08 09:39:56 -06:00
stdout.styledWriteLine(
fgCyan, "oizys", resetStyle, "|",
fgYellow, "WARN", resetStyle, "| ",
args.join("")
)
2024-01-28 11:00:05 -06:00
type
OizysContext = object
2024-01-28 11:00:05 -06:00
flake, host: string
extraArgs: seq[string]
2024-01-28 11:00:05 -06:00
cache = "daylin"
2024-02-19 10:42:07 -06:00
pinix: bool = true
2024-01-28 11:00:05 -06:00
proc execQuit(c: OizysContext, args: varargs[string]) =
let cmd = (@args & c.extraArgs).join(" ")
2024-03-14 10:44:57 -05:00
logInfo "exec: ", cmd
quit (execCmd cmd)
proc newCtx(): OizysContext =
result = OizysContext()
result.flake = getEnv("FLAKE_PATH", getEnv("HOME") / "oizys")
2024-01-28 11:00:05 -06:00
result.host = getHostname()
2024-01-29 10:31:18 -06:00
proc check(c: OizysContext) =
if not dirExists c.flake:
2024-03-14 10:50:11 -05:00
logErr c.flake, "does not exist"
2024-03-14 10:44:57 -05:00
logErr "please use -f/--flake or $FLAKE_PATH"
2024-01-29 10:31:18 -06:00
quit 1
2024-03-14 10:50:11 -05:00
logInfo "flake:", c.flake
logInfo "host:", c.host
2024-01-29 10:31:18 -06:00
2024-02-19 10:42:07 -06:00
proc cmd(c: OizysContext): string {.inline.} =
2024-03-08 09:39:56 -06:00
let pixExists = findExe("pix") != ""
if c.pinix:
if pixExists:
return "pix"
else:
2024-03-14 10:44:57 -05:00
logWarn "pinix not found, falling back to nix"
2024-03-08 09:39:56 -06:00
return "nix"
2024-01-29 10:31:18 -06:00
proc systemFlakePath(c: OizysContext): string =
2024-01-28 11:00:05 -06:00
c.flake & "#nixosConfigurations." & c.host & ".config.system.build.toplevel"
proc build(c: OizysContext) =
2024-01-28 11:00:05 -06:00
## build nixos
execQuit c, c.cmd, "build", c.systemFlakePath
2024-01-28 11:00:05 -06:00
proc dry(c: OizysContext) =
2024-01-28 11:00:05 -06:00
## poor man's nix flake check
execQuit c, c.cmd, "build", c.systemFlakePath, "--dry-run"
2024-01-28 11:00:05 -06:00
proc cache(c: OizysContext) =
2024-03-14 10:44:57 -05:00
## build and push to cachix
2024-01-29 10:49:59 -06:00
let start = now()
2024-01-28 11:00:05 -06:00
let code = execCmd """
cachix watch-exec """ & c.cache & """ \
-- \
nix build """ & c.systemFlakePath & """ \
--print-build-logs \
--accept-flake-config
"""
2024-03-11 10:22:35 -05:00
2024-01-29 10:49:59 -06:00
let duration = (now() - start)
2024-01-28 11:00:05 -06:00
if code != 0:
2024-03-14 10:44:57 -05:00
logErr "failed to build configuration for: ", c.host
2024-03-11 10:22:35 -05:00
quit code
2024-01-28 11:00:05 -06:00
if summaryFile != "":
writeFile(
summaryFile,
"Built host: " & c.host & " in " & $duration & " seconds"
)
2024-03-14 10:44:57 -05:00
logInfo "Built host: " & c.host & " in " & $duration & " seconds"
2024-01-28 11:00:05 -06:00
2024-02-19 10:42:07 -06:00
proc nixosRebuild(c: OizysContext, subcmd: string) =
2024-02-20 13:12:01 -06:00
let cmd = if c.pinix: "pixos-rebuild" else: "nixos-rebuild"
execQuit c, "sudo", cmd, subcmd, "--flake", c.flake
2024-01-28 11:00:05 -06:00
proc boot(c: OizysContext) =
2024-01-28 11:00:05 -06:00
## nixos rebuild boot
nixosRebuild c, "build"
proc switch(c: OizysContext) =
2024-01-28 11:00:05 -06:00
## nixos rebuild switch
nixosRebuild c, "switch"
2024-03-14 10:44:57 -05:00
proc path(c: OizysContext) =
## print nix flake output
echo c.systemFlakePath
const usage = fmt"""
2024-01-28 11:00:05 -06:00
oizys <cmd> [opts]
2024-02-02 16:43:52 -06:00
commands:
2024-03-14 10:44:57 -05:00
dry {dry.doc}
boot {boot.doc}
switch {switch.doc}
cache {cache.doc}
build {build.doc}
path {path.doc}
2024-02-02 16:43:52 -06:00
options:
2024-02-19 10:42:07 -06:00
-h|--help show this help
--host hostname (current host)
-f|--flake path to flake ($FLAKE_PATH or $HOME/oizys)
-c|--cache name of cachix binary cache (daylin)
--no-pinix don't use pinix
2024-01-28 11:00:05 -06:00
"""
2024-01-29 10:31:18 -06:00
proc runCmd(c: OizysContext, cmd: string) =
2024-01-28 11:00:05 -06:00
case cmd:
of "dry": dry c
of "switch": switch c
of "boot": boot c
of "cache": cache c
of "build": build c
2024-03-14 10:44:57 -05:00
of "path": path c
2024-01-28 11:00:05 -06:00
else:
2024-03-14 10:44:57 -05:00
logErr "unknown command: ", cmd
2024-01-28 11:00:05 -06:00
echo usage
quit 1
proc parseFlag(c: var OizysContext, kind: CmdLineKind, key, val: string) =
2024-01-28 11:00:05 -06:00
case key:
2024-02-02 16:43:52 -06:00
of "h", "help":
2024-01-28 11:00:05 -06:00
echo usage; quit 0
2024-01-29 10:06:00 -06:00
of "host":
2024-01-28 11:00:05 -06:00
c.host = val
2024-01-28 12:08:38 -06:00
of "f", "flake":
2024-01-28 11:00:05 -06:00
c.flake = val
2024-02-19 10:42:07 -06:00
of "no-pinix":
c.pinix = false
else:
c.extraArgs.add (if kind == cmdLongOption: "--" else: "-") & key
c.extraArgs.add val
2024-01-28 11:00:05 -06:00
when isMainModule:
var
c = newCtx()
2024-02-19 10:42:07 -06:00
subcmd: string
var p = initOptParser(
longNoVal = @["no-pinix", "help", ""], shortNoVal = {'h'}
)
for kind, key, val in p.getopt():
2024-01-28 11:00:05 -06:00
case kind
of cmdArgument:
2024-02-19 10:42:07 -06:00
subcmd = key
2024-01-28 11:00:05 -06:00
of cmdLongOption, cmdShortOption:
2024-03-13 10:37:48 -05:00
if key == "": break
parseFlag c, kind, key, val
2024-01-28 11:00:05 -06:00
of cmdEnd:
discard
2024-02-19 10:42:07 -06:00
if subcmd == "":
2024-01-28 11:00:05 -06:00
echo "please specify a command"
echo usage; quit 1
c.extraArgs = p.remainingArgs
2024-01-29 10:31:18 -06:00
check c
2024-02-19 10:42:07 -06:00
runCmd c, subcmd