#!/usr/bin/env nu # bootstrap_initial/run.nu — full first-time platform bootstrap def main [ --workspace: string = "" --hetzner-context: string = "" --do-context: string = "" --bootstrap-zot-url: string = "" --s3-bucket: string = "" --ops-vm-host: string = "" --ops-controller-key: string = "" --keeper-key: string = "" --initial-delegate-did: string = "" --skip-golden-image: string = "false" --dry-run ]: nothing -> nothing { let ws = if ($workspace | is-not-empty) { $workspace } else { $env.PLAYBOOK_PARAM_WORKSPACE? | default "libre-wuji" } let htz_ctx = if ($hetzner_context | is-not-empty) { $hetzner_context } else { $env.PLAYBOOK_PARAM_HETZNER_CONTEXT? | default "" } let do_ctx = if ($do_context | is-not-empty) { $do_context } else { $env.PLAYBOOK_PARAM_DO_CONTEXT? | default "" } let bs_zot = if ($bootstrap_zot_url | is-not-empty) { $bootstrap_zot_url } else { $env.PLAYBOOK_PARAM_BOOTSTRAP_ZOT_URL? | default "" } let s3 = if ($s3_bucket | is-not-empty) { $s3_bucket } else { $env.PLAYBOOK_PARAM_S3_BUCKET? | default "libre-wuji-zot" } let vm_host = if ($ops_vm_host | is-not-empty) { $ops_vm_host } else { $env.PLAYBOOK_PARAM_OPS_VM_HOST? | default "" } let ctrl_key = if ($ops_controller_key | is-not-empty) { $ops_controller_key } else { $env.PLAYBOOK_PARAM_OPS_CONTROLLER_KEY? | default "" } let kpr_key = if ($keeper_key | is-not-empty) { $keeper_key } else { $env.PLAYBOOK_PARAM_KEEPER_KEY? | default "" } let delegate_did = if ($initial_delegate_did | is-not-empty) { $initial_delegate_did } else { $env.PLAYBOOK_PARAM_INITIAL_DELEGATE_DID? | default "" } let skip_img = ($skip_golden_image == "true") if ($ws | is-empty) { error make { msg: "workspace is required" } } if ($htz_ctx | is-empty) { error make { msg: "hetzner-context is required" } } let playbook_dir = $env.PLAYBOOK_DIR? | default ($env.FILE_PWD | path expand) let dry_flag = if $dry_run { "--dry-run" } else { "" } print $"[bootstrap_initial] workspace=($ws) dry-run=($dry_run)" print "NOTE: This playbook runs exactly once per platform instantiation." print "" print "[step 1/11] verifying prerequisites..." let r1 = do { ^nu ($playbook_dir | path join "steps/verify_prerequisites.nu") --workspace $ws --hetzner-context $htz_ctx --do-context $do_ctx --bootstrap-zot-url $bs_zot --ops-controller-key $ctrl_key --keeper-key $kpr_key --initial-delegate-did $delegate_did $dry_flag } | complete if $r1.exit_code != 0 { error make { msg: $"Prerequisites check failed: ($r1.stderr | str trim)" } } print $r1.stdout print "[step 2/11] building buildkit-runner golden image..." let r2 = do { ^nu ($playbook_dir | path join "steps/build_golden_image.nu") --skip-if $"($skip_img)" $dry_flag } | complete if $r2.exit_code != 0 { error make { msg: $"Golden image build failed: ($r2.stderr | str trim)" } } print $r2.stdout print "[step 3/11] pushing golden image to bootstrap registry..." let r3 = do { ^nu ($playbook_dir | path join "steps/push_to_bootstrap_zot.nu") --bootstrap-zot-url $bs_zot $dry_flag } | complete if $r3.exit_code != 0 { error make { msg: $"Push to bootstrap registry failed: ($r3.stderr | str trim)" } } print $r3.stdout print "[step 4/11] deploying libre-wuji cluster..." let r4 = do { ^nu ($playbook_dir | path join "steps/deploy_libre_wuji.nu") --workspace $ws --hetzner-context $htz_ctx --bootstrap-zot-url $bs_zot --ops-controller-key $ctrl_key $dry_flag } | complete if $r4.exit_code != 0 { error make { msg: $"libre-wuji deployment failed: ($r4.stderr | str trim)" } } print $r4.stdout print "[step 5/11] waiting for wuji zot to be healthy..." let r5 = do { ^nu ($playbook_dir | path join "steps/verify_wuji_zot_live.nu") --workspace $ws $dry_flag } | complete if $r5.exit_code != 0 { error make { msg: $"wuji zot health check failed: ($r5.stderr | str trim)" } } print $r5.stdout print "[step 6/11] migrating images to wuji zot..." let r6 = do { ^nu ($playbook_dir | path join "steps/migrate_to_wuji_zot.nu") --workspace $ws --bootstrap-zot-url $bs_zot --s3-bucket $s3 $dry_flag } | complete if $r6.exit_code != 0 { error make { msg: $"Image migration to wuji zot failed: ($r6.stderr | str trim)" } } print $r6.stdout print "[step 7/11] bootstrapping Radicle governance..." let r7 = do { ^nu ($playbook_dir | path join "steps/bootstrap_radicle_governance.nu") --workspace $ws --initial-delegate-did $delegate_did $dry_flag } | complete if $r7.exit_code != 0 { error make { msg: $"Radicle governance bootstrap failed: ($r7.stderr | str trim)" } } print $r7.stdout print "[step 8/11] deploying libre-daoshi..." let r8 = do { ^nu ($playbook_dir | path join "steps/deploy_libre_daoshi.nu") --hetzner-context $htz_ctx $dry_flag } | complete if $r8.exit_code != 0 { print $" WARNING: libre-daoshi deployment reported errors: ($r8.stderr | str trim)" } else { print $r8.stdout } print "[step 9/11] deploying ops-vm..." let r9 = do { ^nu ($playbook_dir | path join "steps/deploy_ops_vm.nu") --do-context $do_ctx --keeper-key $kpr_key $dry_flag } | complete if $r9.exit_code != 0 { print $" WARNING: ops-vm deployment reported errors: ($r9.stderr | str trim)" } else { print $r9.stdout } print "[step 10/11] running end-to-end smoke test..." let r10 = do { ^nu ($playbook_dir | path join "steps/verify_end_to_end.nu") --workspace $ws $dry_flag } | complete if $r10.exit_code != 0 { print $" WARNING: end-to-end verification failed: ($r10.stderr | str trim)" } else { print $r10.stdout } print "[step 11/11] emitting bootstrap-complete audit event..." let r11 = do { ^nu ($playbook_dir | path join "steps/emit_audit.nu") --workspace $ws --event-type "bootstrap_complete" $dry_flag } | complete if $r11.exit_code != 0 { print $" WARNING: audit emit failed: ($r11.stderr | str trim)" } print "" print "[bootstrap_initial] complete" print "Next: verify with `prvng playbook run verify_end_to_end` and review ops history" }