nix machine / user configurations
1#!/usr/bin/env nu 2 3use std "path add" 4use std/log 5 6path add /nix/var/nix/profiles/default/bin 7 8cd $env.NH_FLAKE 9 10# load webhook secrets 11rage -d -i ./ssh_key ./secrets/deployWebhook.age | from toml | load-env 12 13def webhook [title: string, content: string, exit_code?: number, ping?: bool = false] { 14 let type = if $exit_code == null { "⌛" } else if $exit_code == 0 { "✔️" } else { "❌" } 15 let msg = { 16 content: (if $ping { "hey <@853064602904166430>!" } else { "" }), 17 embeds: [{ 18 description: $content, 19 title: $"($type) /($title)/", 20 footer: { 21 text: $"(date now) \((sys host | get hostname)\)", 22 } 23 }] 24 } 25 26 if $exit_code == 0 or $exit_code == null { 27 log info $content 28 } else { 29 log error $content 30 } 31 http post --content-type application/json $"https://discord.com/api/webhooks/($env.WEBHOOK_ID)/($env.WEBHOOK_TOKEN)" $msg 32} 33 34def upload-paste []: any -> string { 35 # let paste_url = http post -H ["user-agent" "gaze.systems terra deploy"] --content-type multipart/form-data "https://0x0.st" {file: ($in | to text | into binary), secret: true} 36 # return $paste_url 37 return "" 38} 39 40def time-block [block]: nothing -> record { 41 let start = date now 42 let result = do $block 43 let end = date now 44 return {result: $result, elapsed: ($end - $start)} 45} 46 47let hosts = { 48 wolumonde: { 49 type: "nixos", 50 user: "root", 51 addr: "23.88.101.188", 52 }, 53 "dusk@devel.mobi": { 54 type: "home", 55 user: "dusk", 56 addr: "devel.mobi", 57 }, 58} 59 60def deploy [hostname: string] { 61 log info $"start deploy host ($hostname)" 62 let hooktitle = $"/($hostname)/deploy" 63 let hostcfg = $hosts | get $hostname 64 65 webhook $hooktitle $"=== deploy for ($hostname): started ===\n\n(sys disks | to text)\n\n(sys mem | to text)" 66 67 def run_step [action: string, block]: nothing -> bool { 68 webhook $"($hooktitle)/($action)" $"=== ($action) ($hostname) started ===" 69 let result = time-block { do $block | tee -e {print -r} | tee {print -r} | complete } 70 let failed = $result.result.exit_code != 0 71 webhook $"($hooktitle)/($action)" $"=== ($action) ($hostname) is done ===\n\ntook ($result.elapsed)\n\nlog: ($result.result | upload-paste)" $result.result.exit_code $failed 72 return $failed 73 } 74 75 let result_dir = mktemp -d | path join "result" 76 let build_cmd = { 77 match $hostcfg.type { 78 "nixos" => {nh os build --no-nom -H $hostname -o $result_dir -- -L --show-trace} 79 "home" => {nh home build --no-nom -c $hostname -o $result_dir -- -L --show-trace} 80 } 81 } 82 if (run_step "build" $build_cmd) { 83 return 84 } 85 let result_link = readlink $result_dir 86 87 let target = $"($hostcfg.user)@($hostcfg.addr)" 88 let copy_cmd = {nix copy --to $"ssh://($target)" $result_link} 89 if (run_step "copy to" $copy_cmd) { 90 return 91 } 92 93 let activate_cmd = { 94 let cmd = match $hostcfg.type { 95 "nixos" => $"sudo '($result_link)/bin/switch-to-configuration' 'switch'", 96 "home" => $"($result_link)/activate", 97 } 98 ssh $target $cmd 99 } 100 if (run_step "activate" $activate_cmd) { 101 return 102 } 103 104 webhook $hooktitle $"=== deploy for ($hostname): finished ===" 0 true 105} 106 107def update-inputs []: list<string> -> bool { 108 let inputsText = $in | str join ", " 109 let stashed = try { 110 let stash_result = git stash | complete 111 $stash_result.stdout | str contains "Saved working directory" 112 } catch { 113 false 114 } 115 log info $"trying to update inputs ($inputsText)" 116 let result = nix run .#nvfetcher -- -f $"\(($in | str join '|')\)" | complete 117 let is_ok = ($result.stdout | str contains "Changes:") 118 if $is_ok { 119 let changes_content = $result.stdout | lines | skip until {|line| $line | str contains "Changes:"} | skip 1 | str join "\n" 120 webhook $"/inputs" $"=== updated inputs ===\n\n($changes_content)" $result.exit_code 121 } 122 if $is_ok { 123 # try committing flake updates 124 try { 125 git add _sources 126 git commit -m "chore(nix): update inputs [skip ci]" 127 } 128 } else { 129 try { 130 git restore . 131 } 132 } 133 if $stashed { 134 try { 135 git stash pop 136 } 137 } 138 $is_ok 139} 140 141def main [hostname: string = "wolumonde", --only-deploy (-d)] { 142 webhook "deploy" "=== started deploying ===" 143 144 mut inputs_updated = false 145 if $only_deploy == false { 146 $inputs_updated = ["blog" "limbusart" "nsid-tracker" "tangled"] | update-inputs 147 try { 148 log info "trying to update dns records" 149 nix run ".#dns" -- push 150 } catch { |err| 151 webhook "dns" $"=== error pushing dns ===\n\n($err.msg | to text)" 1 152 } 153 } 154 155 if $hostname == "all" { 156 $hosts | columns | each {|host| deploy $host} 157 } else { 158 deploy $hostname 159 } 160 161 if $inputs_updated { 162 try { git push } 163 } 164}