nix machine / user configurations
at terra 4.9 kB view raw
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 dzwonek: { 54 type: "nixos", 55 user: "root", 56 addr: "94.237.26.47", 57 }, 58 volsinii: { 59 type: "nixos", 60 user: "root", 61 addr: "199.71.188.53", 62 }, 63 trimounts: { 64 type: "nixos", 65 user: "root", 66 addr: "159.195.58.28", 67 }, 68 "dusk@devel.mobi": { 69 type: "home", 70 user: "dusk", 71 addr: "devel.mobi", 72 }, 73} 74 75def deploy [hostname: string] { 76 log info $"start deploy host ($hostname)" 77 let hooktitle = $"/($hostname)/deploy" 78 let hostcfg = $hosts | get $hostname 79 80 webhook $hooktitle $"=== deploy for ($hostname): started ===\n\n(sys disks | to text)\n\n(sys mem | to text)" 81 82 def run_step [action: string, block]: nothing -> bool { 83 webhook $"($hooktitle)/($action)" $"=== ($action) ($hostname) started ===" 84 let result = time-block { do $block | tee -e {print -r} | tee {print -r} | complete } 85 let failed = $result.result.exit_code != 0 86 webhook $"($hooktitle)/($action)" $"=== ($action) ($hostname) is done ===\n\ntook ($result.elapsed)\n\nlog: ($result.result | upload-paste)" $result.result.exit_code $failed 87 return $failed 88 } 89 90 let result_dir = mktemp -d | path join "result" 91 let build_cmd = { 92 match $hostcfg.type { 93 "nixos" => {nh os build --no-nom -H $hostname -o $result_dir -- -L --show-trace} 94 "home" => {nh home build --no-nom -c $hostname -o $result_dir -- -L --show-trace} 95 } 96 } 97 if (run_step "build" $build_cmd) { 98 return 99 } 100 let result_link = readlink $result_dir 101 102 let target = $"($hostcfg.user)@($hostcfg.addr)" 103 let copy_cmd = {nix copy -s --to $"ssh://($target)" $result_link} 104 if (run_step "copy to" $copy_cmd) { 105 return 106 } 107 108 let activate_cmd = { 109 let cmd = match $hostcfg.type { 110 "nixos" => $"sudo '($result_link)/bin/switch-to-configuration' 'switch'", 111 "home" => $"($result_link)/activate", 112 } 113 ssh $target $cmd 114 } 115 if (run_step "activate" $activate_cmd) { 116 return 117 } 118 119 webhook $hooktitle $"=== deploy for ($hostname): finished ===" 0 true 120} 121 122def update-inputs []: list<string> -> bool { 123 let inputsText = $in | str join ", " 124 let stashed = try { 125 let stash_result = git stash | complete 126 $stash_result.stdout | str contains "Saved working directory" 127 } catch { 128 false 129 } 130 log info $"trying to update inputs ($inputsText)" 131 let result = nix run .#nvfetcher -- -f $"\(($in | str join '|')\)" | complete 132 let is_ok = ($result.stdout | str contains "Changes:") 133 if $is_ok { 134 let changes_content = $result.stdout | lines | skip until {|line| $line | str contains "Changes:"} | skip 1 | str join "\n" 135 webhook $"/inputs" $"=== updated inputs ===\n\n($changes_content)" $result.exit_code 136 } 137 if $is_ok { 138 # try committing flake updates 139 try { 140 git add _sources 141 git commit -m "chore(nix): update inputs [skip ci]" 142 } 143 } else { 144 try { 145 git restore . 146 } 147 } 148 if $stashed { 149 try { 150 git stash pop 151 } 152 } 153 $is_ok 154} 155 156def main [hostname: string = "wolumonde", --only-deploy (-d)] { 157 webhook "deploy" "=== started deploying ===" 158 159 mut inputs_updated = false 160 if $only_deploy == false { 161 $inputs_updated = ["blog" "limbusart" "nsid-tracker" "tangled"] | update-inputs 162 try { 163 log info "trying to update dns records" 164 nix run ".#dns" -- push 165 } catch { |err| 166 webhook "dns" $"=== error pushing dns ===\n\n($err.msg | to text)" 1 167 } 168 } 169 170 if $hostname == "all" { 171 $hosts | columns | each {|host| deploy $host} 172 } else { 173 deploy $hostname 174 } 175 176 if $inputs_updated { 177 try { git push } 178 } 179}