@underpostnet/cyberia 3.2.90 → 3.3.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +1 -0
- package/.env.example +16 -0
- package/.github/workflows/coverall.cyberia.ci.yml +107 -0
- package/.github/workflows/cyberia-client.cd.yml +6 -18
- package/.github/workflows/cyberia-server.cd.yml +6 -18
- package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
- package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
- package/.github/workflows/engine-cyberia.cd.yml +6 -78
- package/.github/workflows/engine-cyberia.ci.yml +4 -5
- package/.github/workflows/ghpkg.ci.yml +42 -21
- package/.github/workflows/hardhat.ci.yml +12 -11
- package/.github/workflows/npmpkg.ci.yml +17 -15
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
- package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
- package/.github/workflows/release.cd.yml +2 -9
- package/.prettierignore +1 -0
- package/AGENTS.md +47 -0
- package/CHANGELOG.md +581 -2417
- package/CLI-HELP.md +416 -127
- package/Dockerfile +25 -9
- package/Dockerfile.dev +25 -9
- package/Dockerfile.test +4 -4
- package/README.md +21 -1
- package/bin/build.js +70 -43
- package/bin/build.template.js +8 -3
- package/bin/cyberia.js +372 -135
- package/bin/deploy.js +18 -104
- package/bin/index.js +372 -135
- package/compose.env +16 -0
- package/conf.js +93 -4
- package/deploy/cyberia-client/deploy.sh +47 -0
- package/deploy/cyberia-client/package.sh +18 -0
- package/deploy/cyberia-client/state.sh +14 -0
- package/deploy/cyberia-server/deploy.sh +47 -0
- package/deploy/cyberia-server/package.sh +18 -0
- package/deploy/cyberia-server/state.sh +14 -0
- package/deploy/dd-cyberia/deploy.sh +22 -0
- package/deploy/dd-cyberia/init.sh +55 -0
- package/deploy/dd-cyberia/package.sh +17 -0
- package/deploy/dd-cyberia/state.sh +14 -0
- package/deploy/dd-cyberia/sync-deploy.sh +116 -0
- package/deploy/lib/github-actions-logging.sh +594 -0
- package/deploy/lib/host.sh +185 -0
- package/deploy/lib/state.sh +62 -0
- package/deploy/pwa-microservices-template/deploy.sh +45 -0
- package/deploy/release/deploy.sh +32 -0
- package/deployment.yaml +7 -2
- package/docker-compose.yml +31 -37
- package/examples/static-page/README.md +19 -19
- package/examples/static-page/ssr-components/CustomPage.js +2 -2
- package/hardhat/hardhat.config.js +1 -6
- package/hardhat/package-lock.json +104 -43
- package/hardhat/package.json +3 -3
- package/manifests/alertmanager/deployment.yaml +81 -0
- package/manifests/blackbox-exporter/deployment.yaml +75 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +36 -7
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +77 -0
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/grafana/deployment.yaml +26 -7
- package/manifests/grafana/kustomization.yaml +1 -0
- package/manifests/grafana/service.yaml +6 -1
- package/manifests/mariadb/pv.yaml +1 -0
- package/manifests/mongodb/statefulset.yaml +9 -2
- package/manifests/mysql/pv-pvc.yaml +14 -1
- package/manifests/postgresql/pv.yaml +12 -1
- package/manifests/postgresql/pvc.yaml +1 -0
- package/manifests/prometheus/deployment.yaml +18 -22
- package/package.json +83 -10
- package/scripts/audit-selinux.sh +64 -0
- package/scripts/event-monitor.sh +56 -0
- package/scripts/gpu-diag.sh +0 -0
- package/scripts/ip-info.sh +0 -0
- package/scripts/k3s-node-setup.sh +30 -14
- package/scripts/kubeadm-node-setup.sh +40 -31
- package/scripts/lxd-vm-setup.sh +0 -0
- package/scripts/maas-nat-firewalld.sh +0 -0
- package/scripts/maas-setup.sh +8 -8
- package/scripts/nat-iptables.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +0 -0
- package/scripts/rocky-kickstart.sh +25 -9
- package/scripts/selinux-normalize.sh +907 -0
- package/scripts/shutdown-machine.sh +843 -0
- package/scripts/test-monitor.sh +3 -3
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
- package/src/api/core/core.controller.js +1 -1
- package/src/api/core/core.router.js +2 -2
- package/src/api/core/core.service.js +2 -2
- package/src/api/crypto/crypto.controller.js +1 -1
- package/src/api/crypto/crypto.service.js +1 -1
- package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +1 -1
- package/src/api/cyberia-action/cyberia-action.service.js +2 -2
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
- package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
- package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
- package/src/api/cyberia-instance/cyberia-fallback-default-items.js +63 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +16 -1
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
- package/src/api/cyberia-instance/cyberia-instance.controller.js +4 -1
- package/src/api/cyberia-instance/cyberia-instance.router.js +15 -2
- package/src/api/cyberia-instance/cyberia-instance.service.js +45 -2
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +1 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
- package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
- package/src/api/cyberia-map/cyberia-map.router.js +1 -1
- package/src/api/cyberia-map/cyberia-map.service.js +2 -2
- package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
- package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +16 -29
- package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
- package/src/api/default/default.controller.js +1 -1
- package/src/api/default/default.router.js +1 -1
- package/src/api/default/default.service.js +2 -2
- package/src/api/document/document.controller.js +1 -1
- package/src/api/document/document.router.js +1 -1
- package/src/api/document/document.service.js +2 -2
- package/src/api/file/file.controller.js +1 -1
- package/src/api/file/file.router.js +1 -1
- package/src/api/file/file.service.js +2 -2
- package/src/api/instance/instance.controller.js +1 -1
- package/src/api/instance/instance.router.js +1 -1
- package/src/api/instance/instance.service.js +2 -2
- package/src/api/ipfs/ipfs.controller.js +1 -1
- package/src/api/ipfs/ipfs.router.js +2 -2
- package/src/api/ipfs/ipfs.service.js +2 -2
- package/src/api/object-layer/object-layer.controller.js +1 -1
- package/src/api/object-layer/object-layer.model.js +204 -3
- package/src/api/object-layer/object-layer.router.js +2 -2
- package/src/api/object-layer/object-layer.service.js +4 -17
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
- package/src/api/test/test.controller.js +1 -1
- package/src/api/test/test.service.js +1 -1
- package/src/api/user/guest.service.js +3 -3
- package/src/api/user/user.controller.js +1 -1
- package/src/api/user/user.router.js +2 -2
- package/src/api/user/user.service.js +4 -4
- package/src/api.js +5 -9
- package/src/cli/app.js +391 -0
- package/src/cli/baremetal.js +30 -36
- package/src/cli/client.js +306 -0
- package/src/cli/cloud-init.js +3 -3
- package/src/cli/cluster.js +242 -135
- package/src/cli/db.js +126 -67
- package/src/cli/deploy.js +158 -60
- package/src/cli/docker-compose.js +5 -5
- package/src/cli/domains.js +184 -0
- package/src/cli/dotenv-store.js +143 -0
- package/src/cli/event.js +2281 -0
- package/src/cli/fs.js +3 -3
- package/src/cli/host.js +672 -0
- package/src/cli/image.js +4 -7
- package/src/cli/index.js +426 -134
- package/src/cli/ipfs.js +34 -30
- package/src/cli/kickstart.js +1 -1
- package/src/cli/kubectl.js +218 -41
- package/src/cli/lxd.js +3 -3
- package/src/cli/monitor.js +1359 -26
- package/src/cli/package.js +90 -0
- package/src/cli/release.js +73 -34
- package/src/cli/repository.js +564 -367
- package/src/cli/run.js +362 -654
- package/src/cli/secrets.js +2158 -964
- package/src/cli/ssh.js +651 -331
- package/src/cli/state.js +394 -0
- package/src/cli/static.js +2 -2
- package/src/cli/system.js +26 -13
- package/src/cli/test.js +199 -125
- package/src/cli/vultr.js +623 -0
- package/src/cli/wireguard.js +2930 -0
- package/src/client/components/core/CalendarCore.js +53 -96
- package/src/client/components/core/Docs.js +258 -211
- package/src/client/components/core/FileExplorer.js +0 -21
- package/src/client/components/core/PanelForm.js +4 -4
- package/src/client/components/core/Repository.js +56 -0
- package/src/client/components/core/Translate.js +7 -0
- package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
- package/src/client/components/core/Wallet.js +0 -11
- package/src/client/components/core/Worker.js +7 -1
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
- package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +368 -0
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +35 -1
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +4 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppShellDefault.js +1 -1
- package/src/client/components/default/SettingsDefault.js +2 -2
- package/src/client/components/itemledger/SettingsItemledger.js +2 -2
- package/src/client/components/underpost/AppShellUnderpost.js +3 -2
- package/src/client/components/underpost/SettingsUnderpost.js +2 -2
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +17 -3
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +1 -1
- package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-384x384.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-512x512.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
- package/src/client/public/default/assets/background/white.jpg +0 -0
- package/src/client/public/default/browserconfig.xml +1 -1
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon-48x48.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/manifest.webmanifest +5 -5
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/yandex-browser-50x50.png +0 -0
- package/src/client/public/default/yandex-browser-manifest.json +1 -1
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +40 -0
- package/src/client/services/object-layer/object-layer.management.js +4 -4
- package/src/client/ssr/RootDocument.js +1 -1
- package/src/client/ssr/body/404.js +1 -1
- package/src/client/ssr/body/500.js +1 -1
- package/src/client/ssr/body/CacheControl.js +1 -1
- package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
- package/src/client/ssr/head/CryptokoynScripts.js +1 -1
- package/src/client/ssr/head/Css.js +1 -1
- package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +1 -1
- package/src/client/ssr/head/ItemledgerScripts.js +1 -1
- package/src/client/ssr/head/Microdata.js +1 -1
- package/src/client/ssr/head/Production.js +1 -1
- package/src/client/ssr/head/Pwa.js +1 -1
- package/src/client/ssr/head/PwaItemledger.js +1 -1
- package/src/client/ssr/head/Seo.js +1 -1
- package/src/client/ssr/head/UnderpostScripts.js +1 -1
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
- package/src/client/ssr/views/Cyberia404.js +7 -5
- package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/views/Maintenance.js +1 -1
- package/src/client/ssr/views/NoNetworkConnection.js +1 -1
- package/src/client/ssr/views/Test.js +1 -1
- package/src/client/sw/core.sw.js +20 -14
- package/src/client-builder/client-build-docs.js +61 -46
- package/src/client-builder/client-build-live.js +2 -2
- package/src/client-builder/client-build.js +58 -44
- package/src/client-builder/client-dev-server.js +3 -3
- package/src/client-builder/client-icons.js +2 -2
- package/src/client-builder/ssr.js +3 -3
- package/src/client.build.js +3 -6
- package/src/client.dev.js +3 -6
- package/src/db/DataBaseProvider.js +186 -3
- package/src/db/mariadb/MariaDB.js +3 -2
- package/src/db/mongo/MongoBootstrap.js +273 -101
- package/src/db/mongo/MongooseDB.js +11 -8
- package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
- package/src/grpc/cyberia/grpc-server.js +1 -1
- package/src/index.js +103 -23
- package/src/mailer/EmailRender.js +2 -2
- package/src/mailer/MailerInterceptor.js +87 -0
- package/src/mailer/MailerProvider.js +50 -6
- package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
- package/src/projects/cyberia/besu-genesis-generator.js +3 -3
- package/src/projects/cyberia/catalog-cyberia.js +54 -6
- package/src/projects/cyberia/gemini-client.js +1 -1
- package/src/projects/cyberia/generate-saga.js +15 -24
- package/src/projects/cyberia/hot-reload-trigger.js +1 -1
- package/src/projects/cyberia/instance-data.js +22 -3
- package/src/projects/cyberia/ipfs-client.js +4 -4
- package/src/projects/cyberia/map-preview-generator.js +1 -1
- package/src/projects/cyberia/object-layer.js +12 -22
- package/src/projects/cyberia/semantic-layer-generator.js +1 -1
- package/src/projects/underpost/catalog-underpost.js +13 -2
- package/src/proxy.js +4 -7
- package/src/runtime/cyberia-client/Dockerfile +9 -4
- package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
- package/src/runtime/cyberia-server/Dockerfile +9 -4
- package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
- package/src/runtime/engine-cyberia/Dockerfile +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
- package/src/runtime/engine-cyberia/compose.env +16 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +31 -37
- package/src/runtime/express/Express.js +32 -27
- package/src/runtime/lampp/Lampp.js +22 -70
- package/src/runtime/nginx/Nginx.js +1 -1
- package/src/runtime/wp/Wp.js +16 -48
- package/src/server/{catalog.js → build/catalog.js} +15 -5
- package/src/server/build/coverage.js +117 -0
- package/src/server/build/execution.js +402 -0
- package/src/server/build/package.js +465 -0
- package/src/server/build/testing.js +528 -0
- package/src/server/{dns.js → network/dns.js} +241 -14
- package/src/server/network/forward-proxy.js +541 -0
- package/src/server/{middlewares.js → network/middlewares.js} +59 -4
- package/src/server/network/node-capability.js +98 -0
- package/src/server/{peer.js → network/peer.js} +3 -3
- package/src/server/{proxy.js → network/proxy.js} +7 -13
- package/src/server/network/router.js +356 -0
- package/src/server/{tls.js → network/tls.js} +2 -2
- package/src/server/network/underpost-compression.js +186 -0
- package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +26 -16
- package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +19 -3
- package/src/server/{cri.js → ops/cri.js} +2 -2
- package/src/server/ops/cron.js +949 -0
- package/src/server/ops/event-notification.js +284 -0
- package/src/server/{logger.js → ops/logger.js} +108 -23
- package/src/server/ops/monitoring.js +1724 -0
- package/src/server/ops/systemd.js +259 -0
- package/src/server/{conf.js → runtime/conf.js} +521 -520
- package/src/server/runtime/config-scope.js +215 -0
- package/src/server/runtime/environment.js +149 -0
- package/src/server/{process.js → runtime/process.js} +153 -13
- package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
- package/src/server/{runtime.js → runtime/runtime.js} +12 -8
- package/src/server/{start.js → runtime/start.js} +128 -39
- package/src/server/{auth.js → security/auth.js} +7 -8
- package/src/server/security/container-storage.js +382 -0
- package/src/server/{crypto.js → security/crypto.js} +1 -1
- package/src/server/security/selinux.js +185 -0
- package/src/server/{backup.js → storage/backup.js} +17 -8
- package/src/server/{data-query.js → storage/data-query.js} +1 -1
- package/src/server/{downloader.js → storage/downloader.js} +2 -2
- package/src/server/storage/repository.js +68 -0
- package/src/server.js +4 -7
- package/src/ws/IoInterface.js +1 -1
- package/src/ws/IoServer.js +1 -1
- package/src/ws/core/core.ws.connection.js +1 -1
- package/src/ws/core/core.ws.emit.js +1 -1
- package/src/ws/core/core.ws.server.js +1 -1
- package/src/ws/default/default.ws.connection.js +1 -1
- package/src/ws/default/default.ws.emit.js +1 -1
- package/src/ws/default/default.ws.server.js +1 -1
- package/test/e2e/event-e2e-public-ingress-down.js +45 -0
- package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
- package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
- package/test/{api.test.js → integration/app/api.test.js} +33 -14
- package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
- package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +2 -1
- package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
- package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
- package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
- package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
- package/test/integration/infra/1-security/config-scope.test.js +305 -0
- package/test/integration/infra/1-security/container-storage.test.js +356 -0
- package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
- package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
- package/test/integration/infra/1-security/selinux.test.js +69 -0
- package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
- package/test/integration/infra/1-security/systemd-service.test.js +70 -0
- package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
- package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
- package/test/integration/infra/2-network/node-capability.test.js +182 -0
- package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
- package/test/integration/infra/2-network/wireguard-edge.test.js +1731 -0
- package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
- package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
- package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
- package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
- package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
- package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
- package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +47 -6
- package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +56 -4
- package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
- package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
- package/test/integration/infra/5-observability/event-notification.test.js +197 -0
- package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
- package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
- package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
- package/test/support/shell-harness.js +73 -0
- package/test/unit/build-template.test.js +97 -0
- package/test/unit/build-workflow-offline.test.js +132 -0
- package/test/unit/catalog.test.js +71 -0
- package/test/unit/client-build-docs.test.js +334 -0
- package/test/unit/conf-loading.test.js +303 -0
- package/test/unit/conf-resolution.test.js +979 -0
- package/test/unit/coverage-artifact.test.js +130 -0
- package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
- package/test/unit/deploy-env-resolution.test.js +38 -0
- package/test/unit/deploy-log-table.test.js +447 -0
- package/test/unit/execution-profiles.test.js +219 -0
- package/test/unit/fleet-sync-source.test.js +149 -0
- package/test/unit/logger-redaction.test.js +112 -0
- package/test/unit/package.test.js +403 -0
- package/test/unit/prepare-host.test.js +299 -0
- package/test/unit/process-environment.test.js +18 -0
- package/test/unit/propagation-message.test.js +78 -0
- package/test/unit/redeploy-plan.test.js +24 -0
- package/test/unit/release-bump.test.js +474 -0
- package/test/unit/ssh-output-redaction.test.js +28 -0
- package/test/unit/start-options.test.js +46 -0
- package/test/unit/test-tiers.test.js +193 -0
- package/vitest.config.js +58 -0
- package/.nycrc +0 -9
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
- package/manifests/mongodb/pv-pvc.yaml +0 -59
- package/scripts/link-local-underpost-cli.sh +0 -6
- package/src/api/user/user.build.js +0 -16
- package/src/cli/env.js +0 -177
- package/src/client/components/core/Blockchain.js +0 -41
- package/src/client/components/core/Blog.js +0 -9
- package/src/client/components/core/KeyboardAvoidance.js +0 -145
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/white0-min.jpg +0 -0
- package/src/client/public/default/assets/background/white0.jpg +0 -0
- package/src/client/public/doc/favicon.ico +0 -0
- package/src/client/public/doc/sitemap +0 -148
- package/src/server/cron.js +0 -476
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
# Logging helpers for deploy/<deploy-id>/*.sh. Sourced, never executed directly.
|
|
2
|
+
#
|
|
3
|
+
# Deploy script contract:
|
|
4
|
+
# - deploy_start once for the run's title, prepare_host from lib/host.sh next,
|
|
5
|
+
# then one deploy_step call per remote command, each with its own label
|
|
6
|
+
# - the body lives in main(), invoked on the last line: the first remote command
|
|
7
|
+
# pulls this repository, rewriting the running script while bash reads it
|
|
8
|
+
#
|
|
9
|
+
# deploy_step is the entry point every deploy script uses. run_quiet stays the
|
|
10
|
+
# mechanism underneath it, for the rare caller that needs a different report
|
|
11
|
+
# pattern or passthrough window.
|
|
12
|
+
#
|
|
13
|
+
# run_quiet hides normal output and returns the command's exit status so
|
|
14
|
+
# `set -e` stops the deployment. Lines matching `patterns` that parse as a
|
|
15
|
+
# deployment pod report are folded into a table — one row per pod, three columns
|
|
16
|
+
# wide — instead of being streamed; the monitor's raw `deploy-monitor` JSON emits
|
|
17
|
+
# are consumed into that table's cells rather than printed. The monitor
|
|
18
|
+
# iteration and its clock are per frame, not per pod, so they title the table
|
|
19
|
+
# rather than repeating down a column of every row. Anything else within
|
|
20
|
+
# `lines_after` lines of a match scrolls above the table. On failure it keeps
|
|
21
|
+
# two temp files and prints their paths in red instead of their contents: the
|
|
22
|
+
# error trace and the full unfiltered log up to the error. The trace is stderr
|
|
23
|
+
# plus the failing tail of the merged log, because the engine CLI reports through
|
|
24
|
+
# its logger and that writes to stdout — stderr alone routinely holds nothing but
|
|
25
|
+
# git progress output.
|
|
26
|
+
#
|
|
27
|
+
# The table renders three ways, because a log viewer is not a terminal:
|
|
28
|
+
# - terminal: redrawn in place, cursor relative, one frame at a time
|
|
29
|
+
# - CI (GITHUB_ACTIONS/RUN_QUIET_CI): no cursor addressing exists there, so the
|
|
30
|
+
# changed rows stream inside a collapsed `::group::` and the final table is
|
|
31
|
+
# printed after it, expanded
|
|
32
|
+
# - anywhere else: changed rows appended
|
|
33
|
+
# Colour is ANSI SGR only and is emitted in all three (GitHub renders SGR in
|
|
34
|
+
# step logs); NO_COLOR or RUN_QUIET_PLAIN turns it off.
|
|
35
|
+
|
|
36
|
+
if [ -n "${NO_COLOR:-}${RUN_QUIET_PLAIN:-}" ]; then
|
|
37
|
+
RUN_QUIET_RED=''
|
|
38
|
+
RUN_QUIET_RESET=''
|
|
39
|
+
else
|
|
40
|
+
RUN_QUIET_RED=$'\033[0;31m'
|
|
41
|
+
RUN_QUIET_RESET=$'\033[0m'
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
RUN_QUIET_NODE_NAME=$(hostname 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
|
45
|
+
RUN_QUIET_NODE_TAG=${RUN_QUIET_NODE_NAME:+ [$RUN_QUIET_NODE_NAME]}
|
|
46
|
+
|
|
47
|
+
# The report pattern and the passthrough window describe the deployment log
|
|
48
|
+
# format, not any one step, so they are declared once here instead of being
|
|
49
|
+
# repeated at every call site.
|
|
50
|
+
DEPLOY_REPORT_PATTERN='Target pod:'
|
|
51
|
+
DEPLOY_REPORT_LINES_AFTER=14
|
|
52
|
+
|
|
53
|
+
# Titles a deploy run, in the same shape as the step lines below it.
|
|
54
|
+
deploy_start() {
|
|
55
|
+
echo "$RUN_QUIET_NODE_TAG $(date -Is) ▶▶ $1"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# One deploy step: a label and the command that carries it.
|
|
59
|
+
deploy_step() {
|
|
60
|
+
local label="$1"
|
|
61
|
+
shift
|
|
62
|
+
|
|
63
|
+
run_quiet "$label" "$DEPLOY_REPORT_PATTERN" "$DEPLOY_REPORT_LINES_AFTER" "$@"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
run_quiet() {
|
|
67
|
+
local label="$1"
|
|
68
|
+
local patterns="$2"
|
|
69
|
+
local lines_after="$3"
|
|
70
|
+
shift 3
|
|
71
|
+
|
|
72
|
+
local debug_log
|
|
73
|
+
local error_log
|
|
74
|
+
local fail_flag
|
|
75
|
+
local fatal
|
|
76
|
+
local reason
|
|
77
|
+
local fifo_dir
|
|
78
|
+
local filter_pid
|
|
79
|
+
local stderr_pid
|
|
80
|
+
local color=0
|
|
81
|
+
local groups=0
|
|
82
|
+
local redraw=0
|
|
83
|
+
local width=0
|
|
84
|
+
local rows=0
|
|
85
|
+
local status=0
|
|
86
|
+
|
|
87
|
+
echo "$RUN_QUIET_NODE_TAG $(date -Is) ▶ $label"
|
|
88
|
+
|
|
89
|
+
[ -n "${NO_COLOR:-}${RUN_QUIET_PLAIN:-}" ] || color=1
|
|
90
|
+
|
|
91
|
+
if [ -t 1 ] && [ "${TERM:-dumb}" != dumb ] && [ -z "${RUN_QUIET_PLAIN:-}" ]; then
|
|
92
|
+
redraw=1
|
|
93
|
+
width=${COLUMNS:-0}
|
|
94
|
+
[ "$width" -gt 0 ] 2>/dev/null || width=$(tput cols 2>/dev/null || echo 0)
|
|
95
|
+
rows=${LINES:-0}
|
|
96
|
+
[ "$rows" -gt 0 ] 2>/dev/null || rows=$(tput lines 2>/dev/null || echo 0)
|
|
97
|
+
# Without a known width a long row wraps, and the cursor-up count that
|
|
98
|
+
# addresses the table no longer matches the lines it printed.
|
|
99
|
+
[ "$width" -ge 20 ] || redraw=0
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
if [ "$redraw" -eq 0 ] && [ -z "${RUN_QUIET_PLAIN:-}" ] && [ -n "${GITHUB_ACTIONS:-}${RUN_QUIET_CI:-}" ]; then
|
|
103
|
+
groups=1
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
debug_log=$(mktemp --suffix=.debug.log)
|
|
107
|
+
error_log=$(mktemp --suffix=.error.log)
|
|
108
|
+
fail_flag=$(mktemp --suffix=.fatal)
|
|
109
|
+
: >"$fail_flag"
|
|
110
|
+
fifo_dir=$(mktemp -d)
|
|
111
|
+
mkfifo "$fifo_dir/merged" "$fifo_dir/stderr"
|
|
112
|
+
|
|
113
|
+
# The filter reads the live stream rather than the finished log: a deployment
|
|
114
|
+
# monitor prints its report for minutes before exiting, so a pass over the
|
|
115
|
+
# completed file would show nothing until then. fflush defeats awk's block
|
|
116
|
+
# buffering, which otherwise withholds output whenever stdout is a pipe.
|
|
117
|
+
# awk writes the debug log itself rather than piping through tee, so the
|
|
118
|
+
# reader stays a single process that a kill can always release.
|
|
119
|
+
#
|
|
120
|
+
# On a terminal the table is the only live region and always sits at the
|
|
121
|
+
# bottom: rows are overwritten one by one (cursor up, then erase to end of
|
|
122
|
+
# line as each row is rewritten) so the section never blanks between frames,
|
|
123
|
+
# and a passthrough line is printed after erasing the table and before
|
|
124
|
+
# drawing it again. All of that is cursor relative, so every row must occupy
|
|
125
|
+
# exactly one terminal line: rows are cut to the terminal width, counting
|
|
126
|
+
# display columns rather than bytes so colour escapes neither inflate the
|
|
127
|
+
# measurement nor get sliced in half. Elsewhere nothing is cut and nothing
|
|
128
|
+
# is overwritten — the frames stream, folded into a CI group when there is
|
|
129
|
+
# one to fold them into.
|
|
130
|
+
awk \
|
|
131
|
+
-v pattern="$patterns" \
|
|
132
|
+
-v lines_after="$lines_after" \
|
|
133
|
+
-v debug_log="$debug_log" \
|
|
134
|
+
-v redraw="$redraw" \
|
|
135
|
+
-v color="$color" \
|
|
136
|
+
-v groups="$groups" \
|
|
137
|
+
-v label="$label" \
|
|
138
|
+
-v width="$width" \
|
|
139
|
+
-v rows="$rows" \
|
|
140
|
+
-v started="$(date +%H:%M:%S)" \
|
|
141
|
+
-v fail_flag="$fail_flag" \
|
|
142
|
+
-v handoff="$RUN_QUIET_NODE_TAG $(date -Is) ▶ Switch traffic" '
|
|
143
|
+
function strip(s) {
|
|
144
|
+
gsub(esc_seq, "", s)
|
|
145
|
+
return s
|
|
146
|
+
}
|
|
147
|
+
function pad(s, w) {
|
|
148
|
+
while (length(s) < w) s = s " "
|
|
149
|
+
return s
|
|
150
|
+
}
|
|
151
|
+
# Pod names differ in their tail, so a name too wide for its column keeps
|
|
152
|
+
# the end rather than the deploy prefix every pod shares.
|
|
153
|
+
function trim(s, w) {
|
|
154
|
+
return length(s) <= w ? s : ".." substr(s, length(s) - w + 3)
|
|
155
|
+
}
|
|
156
|
+
function rule(n, r) {
|
|
157
|
+
r = ""
|
|
158
|
+
while (n-- > 0) r = r "-"
|
|
159
|
+
return r
|
|
160
|
+
}
|
|
161
|
+
function paint(s, sgr) {
|
|
162
|
+
return color ? esc "[" sgr "m" s esc "[0m" : s
|
|
163
|
+
}
|
|
164
|
+
function fit(s, out, visible) {
|
|
165
|
+
if (!redraw) return s
|
|
166
|
+
out = ""
|
|
167
|
+
visible = 0
|
|
168
|
+
while (length(s) > 0) {
|
|
169
|
+
if (match(s, "^" esc_seq)) {
|
|
170
|
+
out = out substr(s, 1, RLENGTH)
|
|
171
|
+
s = substr(s, RLENGTH + 1)
|
|
172
|
+
continue
|
|
173
|
+
}
|
|
174
|
+
if (visible >= width - 1) return out esc "[0m"
|
|
175
|
+
out = out substr(s, 1, 1)
|
|
176
|
+
s = substr(s, 2)
|
|
177
|
+
visible++
|
|
178
|
+
}
|
|
179
|
+
return out
|
|
180
|
+
}
|
|
181
|
+
function put(line) {
|
|
182
|
+
printf "%s%s\n", fit(line), redraw ? esc "[K" : ""
|
|
183
|
+
fflush()
|
|
184
|
+
}
|
|
185
|
+
# GitHub renders no cursor motion, so the live region becomes a
|
|
186
|
+
# collapsed section: every frame streams into it and the settled table
|
|
187
|
+
# is reprinted outside it.
|
|
188
|
+
function open_group() {
|
|
189
|
+
if (!groups || group_open) return
|
|
190
|
+
group_open = 1
|
|
191
|
+
printf "::group::%s monitor frames\n", label
|
|
192
|
+
fflush()
|
|
193
|
+
}
|
|
194
|
+
function close_group() {
|
|
195
|
+
if (!group_open) return
|
|
196
|
+
group_open = 0
|
|
197
|
+
# The next run of rows opens its own section, and a section starts
|
|
198
|
+
# with its title and header.
|
|
199
|
+
appended_header = 0
|
|
200
|
+
appended_cycle = 0
|
|
201
|
+
printf "::endgroup::\n"
|
|
202
|
+
fflush()
|
|
203
|
+
}
|
|
204
|
+
function final_table( i) {
|
|
205
|
+
if (!groups || pod_count == 0) return
|
|
206
|
+
close_group()
|
|
207
|
+
measure()
|
|
208
|
+
title_line()
|
|
209
|
+
header_lines()
|
|
210
|
+
for (i = 1; i <= pod_count; i++) pod_line(pods[i])
|
|
211
|
+
}
|
|
212
|
+
function json_value(key, found) {
|
|
213
|
+
if (!match($0, "\"" key "\"[ ]*:[ ]*\"[^\"]*\"")) return ""
|
|
214
|
+
found = substr($0, RSTART, RLENGTH)
|
|
215
|
+
sub("^\"" key "\"[ ]*:[ ]*\"", "", found)
|
|
216
|
+
sub("\"$", "", found)
|
|
217
|
+
return found
|
|
218
|
+
}
|
|
219
|
+
function apply_event( was_k8s_ready, was_runtime_ready, i) {
|
|
220
|
+
events_seen = 1
|
|
221
|
+
was_k8s_ready = k8s_ready
|
|
222
|
+
was_runtime_ready = runtime_ready
|
|
223
|
+
if (event_phase == "kubernetes") k8s_ready = (event_state == "pod_ready")
|
|
224
|
+
else if (event_phase == "runtime") {
|
|
225
|
+
runtime_ready = (event_state == "runtime_ready")
|
|
226
|
+
if (event_status != "") last_runtime = event_status
|
|
227
|
+
if (is_fatal(event_status)) note_fatal("runtime event", "status=" event_status)
|
|
228
|
+
}
|
|
229
|
+
if (redraw) {
|
|
230
|
+
if (drawn > 0) {
|
|
231
|
+
clear_table()
|
|
232
|
+
draw_table()
|
|
233
|
+
}
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
# Readiness reaches the cells through the events alone, so without a
|
|
237
|
+
# live table it is the only thing that can move a row.
|
|
238
|
+
if (was_k8s_ready == k8s_ready && was_runtime_ready == runtime_ready) return
|
|
239
|
+
for (i = 1; i <= pod_count; i++) append_row(pods[i])
|
|
240
|
+
}
|
|
241
|
+
# Both phases confirmed is the monitor signing off; the hand-off waits
|
|
242
|
+
# for the report lines of that iteration so the table lands on its final
|
|
243
|
+
# frame first.
|
|
244
|
+
function ready_pending() {
|
|
245
|
+
return events_seen ? (k8s_ready && runtime_ready) : all_pods_running()
|
|
246
|
+
}
|
|
247
|
+
# One report line per pod: "Target pod: NAME | Pod status: X | Runtime status: Y".
|
|
248
|
+
function read_pod_line(line, plain, cell, pod, k8s, runtime) {
|
|
249
|
+
plain = strip(line)
|
|
250
|
+
if (plain !~ /^Target pod: /) return 0
|
|
251
|
+
if (split(plain, cell, / \| /) < 3) return 0
|
|
252
|
+
pod = cell[1]; sub(/^Target pod:[ ]*/, "", pod)
|
|
253
|
+
k8s = cell[2]; sub(/^Pod status:[ ]*/, "", k8s)
|
|
254
|
+
runtime = cell[3]; sub(/^Runtime status:[ ]*/, "", runtime)
|
|
255
|
+
if (pod == "") return 0
|
|
256
|
+
if (is_fatal(runtime)) note_fatal("pod " pod, "runtime status=" runtime)
|
|
257
|
+
if (!(pod in pod_row)) {
|
|
258
|
+
pod_row[pod] = ++pod_count
|
|
259
|
+
pods[pod_count] = pod
|
|
260
|
+
}
|
|
261
|
+
# The report itself is unstamped: the clock is the one the monitor
|
|
262
|
+
# printed for this iteration, so the title advances with the run.
|
|
263
|
+
cycle_time = last_time != "" ? last_time : started
|
|
264
|
+
pod_k8s[pod] = k8s
|
|
265
|
+
pod_runtime[pod] = runtime
|
|
266
|
+
current_pod = pod
|
|
267
|
+
return 1
|
|
268
|
+
}
|
|
269
|
+
# Every pod reporting its expected runtime status with no pending
|
|
270
|
+
# marker is what the deployment itself calls ready. `error` is
|
|
271
|
+
# the fatal value in the RUNTIME_STATUS contract: a terminal state, not a
|
|
272
|
+
# ready one, and reading it as ready handed off to the traffic switch on
|
|
273
|
+
# a deployment that had already failed.
|
|
274
|
+
function all_pods_running( i, pod, runtime) {
|
|
275
|
+
if (pod_count == 0) return 0
|
|
276
|
+
for (i = 1; i <= pod_count; i++) {
|
|
277
|
+
pod = pods[i]
|
|
278
|
+
if (pod_k8s[pod] != "Running") return 0
|
|
279
|
+
runtime = runtime_cell(pod)
|
|
280
|
+
if (runtime == "" || runtime ~ /pending/ || is_fatal(runtime)) return 0
|
|
281
|
+
}
|
|
282
|
+
return 1
|
|
283
|
+
}
|
|
284
|
+
# The bare contract value, not a substring: a phase name that merely
|
|
285
|
+
# contains it (or a log line quoting it) is not a fatal latch.
|
|
286
|
+
function is_fatal(status) {
|
|
287
|
+
return status == "error"
|
|
288
|
+
}
|
|
289
|
+
# Stack frames and source URLs carry absolute host paths and module layout,
|
|
290
|
+
# which must not reach a CI transcript. Both log files still hold them.
|
|
291
|
+
function is_trace(line) {
|
|
292
|
+
return line ~ /^[ \t]*at [^ ]/ || line ~ /file:\/\/\// || line ~ /^[ \t]*at async / || line ~ /^[A-Za-z_]*Error: /
|
|
293
|
+
}
|
|
294
|
+
# Records the fatal latch for run_quiet. A step can report this and still
|
|
295
|
+
# exit 0 — the in-pod lifecycle deliberately does not crash the container
|
|
296
|
+
# — so the exit status alone cannot be trusted to stop the deployment.
|
|
297
|
+
function note_fatal(source, detail) {
|
|
298
|
+
if (fatal_seen) return
|
|
299
|
+
fatal_seen = 1
|
|
300
|
+
printf "%s: %s\n", source, detail > fail_flag
|
|
301
|
+
close(fail_flag)
|
|
302
|
+
}
|
|
303
|
+
# The table stops being a live region here: the deployment is handing
|
|
304
|
+
# over to the traffic switch, so the last frame stays on screen and the
|
|
305
|
+
# chatter the runner prints below it is dropped.
|
|
306
|
+
function hand_off() {
|
|
307
|
+
handed_off = 1
|
|
308
|
+
remaining = 0
|
|
309
|
+
drawn = 0
|
|
310
|
+
last_pod_line = 0
|
|
311
|
+
final_table()
|
|
312
|
+
put(handoff)
|
|
313
|
+
}
|
|
314
|
+
# A later monitor in the same command (a second colour, a rollback) opens
|
|
315
|
+
# its own table below the one that was handed off.
|
|
316
|
+
function reset_table() {
|
|
317
|
+
close_group()
|
|
318
|
+
handed_off = 0
|
|
319
|
+
events_seen = 0
|
|
320
|
+
k8s_ready = 0
|
|
321
|
+
runtime_ready = 0
|
|
322
|
+
pod_count = 0
|
|
323
|
+
cycles = 0
|
|
324
|
+
cycle_time = ""
|
|
325
|
+
appended_header = 0
|
|
326
|
+
appended_cycle = 0
|
|
327
|
+
drawn = 0
|
|
328
|
+
delete pods
|
|
329
|
+
delete pod_row
|
|
330
|
+
delete pod_k8s
|
|
331
|
+
delete pod_runtime
|
|
332
|
+
delete last_row
|
|
333
|
+
}
|
|
334
|
+
# pod_ready is a deployment-wide event: it only annotates a pod whose
|
|
335
|
+
# own phase already agrees, never a stale one still coming up.
|
|
336
|
+
function k8s_cell(pod, cell) {
|
|
337
|
+
cell = pod_k8s[pod]
|
|
338
|
+
return (k8s_ready && cell == "Running") ? cell " (ready)" : cell
|
|
339
|
+
}
|
|
340
|
+
function runtime_cell(pod) {
|
|
341
|
+
return pod_runtime[pod] != "" ? pod_runtime[pod] : last_runtime
|
|
342
|
+
}
|
|
343
|
+
# Columns only ever grow: a cell that shrinks must not reflow the table
|
|
344
|
+
# under the reader between frames.
|
|
345
|
+
function measure( i, pod, over, budget) {
|
|
346
|
+
for (i = 1; i <= pod_count; i++) {
|
|
347
|
+
pod = pods[i]
|
|
348
|
+
if (length(pod) > w_pod) w_pod = length(pod)
|
|
349
|
+
if (length(k8s_cell(pod)) > w_k8s) w_k8s = length(k8s_cell(pod))
|
|
350
|
+
if (length(runtime_cell(pod)) > w_runtime) w_runtime = length(runtime_cell(pod))
|
|
351
|
+
}
|
|
352
|
+
# 10 columns of borders and padding. On a narrow terminal the pod
|
|
353
|
+
# column gives up room first, then the status columns, before fit()
|
|
354
|
+
# starts cutting cells off the right edge.
|
|
355
|
+
w_pod_fit = w_pod
|
|
356
|
+
w_runtime_fit = w_runtime
|
|
357
|
+
w_k8s_fit = w_k8s
|
|
358
|
+
# A streamed table cannot re-pad the rows it already printed, so the
|
|
359
|
+
# status columns start wide enough for the values the monitor is
|
|
360
|
+
# known to report and stop drifting under the header.
|
|
361
|
+
if (!redraw) {
|
|
362
|
+
if (w_k8s_fit < 17) w_k8s_fit = 17
|
|
363
|
+
if (w_runtime_fit < 28) w_runtime_fit = 28
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
# fit() cuts the last column, so the row has to land inside it.
|
|
367
|
+
budget = width - 1
|
|
368
|
+
over = row_width() - budget
|
|
369
|
+
if (over > 0) {
|
|
370
|
+
w_pod_fit = w_pod_fit - over < 12 ? 12 : w_pod_fit - over
|
|
371
|
+
over = row_width() - budget
|
|
372
|
+
}
|
|
373
|
+
if (over > 0) {
|
|
374
|
+
w_runtime_fit = w_runtime_fit - over < 16 ? 16 : w_runtime_fit - over
|
|
375
|
+
over = row_width() - budget
|
|
376
|
+
}
|
|
377
|
+
if (over > 0) w_k8s_fit = w_k8s_fit - over < 12 ? 12 : w_k8s_fit - over
|
|
378
|
+
}
|
|
379
|
+
function row_width() {
|
|
380
|
+
return w_pod_fit + w_k8s_fit + w_runtime_fit + 10
|
|
381
|
+
}
|
|
382
|
+
# The iteration and the clock are one per frame, not one per pod: they
|
|
383
|
+
# title the table instead of repeating down two columns of it.
|
|
384
|
+
function title_line() {
|
|
385
|
+
put(paint(sprintf("%s (refresh #%d, %s)", label, cycles,
|
|
386
|
+
cycle_time != "" ? cycle_time : started), "1"))
|
|
387
|
+
}
|
|
388
|
+
function header_lines() {
|
|
389
|
+
put(paint(sprintf("| %s | %s | %s |", pad("POD NAME", w_pod_fit),
|
|
390
|
+
pad("K8S STATUS", w_k8s_fit), pad("RUNTIME STATUS", w_runtime_fit)), "1"))
|
|
391
|
+
put(paint(sprintf("|%s|%s|%s|", rule(w_pod_fit + 2), rule(w_k8s_fit + 2),
|
|
392
|
+
rule(w_runtime_fit + 2)), "2"))
|
|
393
|
+
}
|
|
394
|
+
function pod_line(pod, runtime) {
|
|
395
|
+
runtime = runtime_cell(pod)
|
|
396
|
+
put(sprintf("| %s | %s | %s |",
|
|
397
|
+
paint(pad(trim(pod, w_pod_fit), w_pod_fit), "1"),
|
|
398
|
+
paint(pad(trim(k8s_cell(pod), w_k8s_fit), w_k8s_fit), k8s_ready ? "32" : "33"),
|
|
399
|
+
paint(pad(trim(runtime, w_runtime_fit), w_runtime_fit), (runtime ~ /pending/ || !runtime_ready) ? "36" : "32")))
|
|
400
|
+
}
|
|
401
|
+
function clear_table() {
|
|
402
|
+
if (!redraw || drawn == 0) return
|
|
403
|
+
printf "%s[%dA%s[J", esc, drawn, esc
|
|
404
|
+
drawn = 0
|
|
405
|
+
}
|
|
406
|
+
function draw_table( i) {
|
|
407
|
+
if (!redraw || pod_count == 0) return
|
|
408
|
+
# A table taller than the screen scrolls, and the cursor-up count no
|
|
409
|
+
# longer addresses the rows it drew; degrade to appended rows.
|
|
410
|
+
if (rows > 0 && pod_count + 3 >= rows) {
|
|
411
|
+
redraw = 0
|
|
412
|
+
drawn = 0
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
measure()
|
|
416
|
+
title_line()
|
|
417
|
+
header_lines()
|
|
418
|
+
for (i = 1; i <= pod_count; i++) pod_line(pods[i])
|
|
419
|
+
drawn = pod_count + 3
|
|
420
|
+
}
|
|
421
|
+
# Without a live table a row is only worth printing when its cells
|
|
422
|
+
# actually moved; the iteration count alone is not a change. The title is
|
|
423
|
+
# reprinted whenever a later iteration is the one moving rows, so a
|
|
424
|
+
# streamed row is still dated without carrying its own clock column.
|
|
425
|
+
function append_row(pod, cells) {
|
|
426
|
+
cells = pod "|" k8s_cell(pod) "|" runtime_cell(pod)
|
|
427
|
+
if (cells == last_row[pod]) return
|
|
428
|
+
last_row[pod] = cells
|
|
429
|
+
measure()
|
|
430
|
+
open_group()
|
|
431
|
+
if (appended_cycle != cycles) {
|
|
432
|
+
title_line()
|
|
433
|
+
appended_cycle = cycles
|
|
434
|
+
}
|
|
435
|
+
if (!appended_header) {
|
|
436
|
+
header_lines()
|
|
437
|
+
appended_header = 1
|
|
438
|
+
}
|
|
439
|
+
pod_line(pod)
|
|
440
|
+
}
|
|
441
|
+
BEGIN {
|
|
442
|
+
w_pod = length("POD NAME")
|
|
443
|
+
w_k8s = length("K8S STATUS")
|
|
444
|
+
w_runtime = length("RUNTIME STATUS")
|
|
445
|
+
group_open = 0
|
|
446
|
+
esc = sprintf("%c", 27)
|
|
447
|
+
esc_seq = esc "\\[[0-9;]*[A-Za-z]"
|
|
448
|
+
clock = "[0-9][0-9]:[0-9][0-9]:[0-9][0-9]"
|
|
449
|
+
json_open = "deploy-monitor:[ ]*[{]"
|
|
450
|
+
json_close = "^[ \t]*[}],?[ \t]*$"
|
|
451
|
+
}
|
|
452
|
+
{
|
|
453
|
+
print > debug_log
|
|
454
|
+
# The monitor stamps its own lines in local time; the ISO field
|
|
455
|
+
# inside an emit is UTC, so it never feeds the column.
|
|
456
|
+
if ($0 !~ /"timestamp"/ && match(strip($0), clock)) last_time = substr(strip($0), RSTART, RLENGTH)
|
|
457
|
+
}
|
|
458
|
+
{
|
|
459
|
+
if (!handed_off && $0 !~ pattern && ready_pending()) hand_off()
|
|
460
|
+
if (handed_off) {
|
|
461
|
+
if ($0 !~ pattern) next
|
|
462
|
+
reset_table()
|
|
463
|
+
}
|
|
464
|
+
# The monitor JSON is state already carried by the table cells: it is
|
|
465
|
+
# consumed here and never reaches the terminal.
|
|
466
|
+
if (in_json) {
|
|
467
|
+
if ($0 ~ json_close) {
|
|
468
|
+
in_json = 0
|
|
469
|
+
apply_event()
|
|
470
|
+
} else {
|
|
471
|
+
if (json_value("phase") != "") event_phase = json_value("phase")
|
|
472
|
+
if (json_value("state") != "") event_state = json_value("state")
|
|
473
|
+
if (json_value("status") != "") event_status = json_value("status")
|
|
474
|
+
}
|
|
475
|
+
if (remaining > 0) remaining--
|
|
476
|
+
last_pod_line = 0
|
|
477
|
+
next
|
|
478
|
+
}
|
|
479
|
+
if ($0 ~ json_open) {
|
|
480
|
+
in_json = 1
|
|
481
|
+
event_phase = event_state = event_status = ""
|
|
482
|
+
if (remaining > 0) remaining--
|
|
483
|
+
last_pod_line = 0
|
|
484
|
+
next
|
|
485
|
+
}
|
|
486
|
+
if (read_pod_line($0)) {
|
|
487
|
+
# Pod reports arrive back to back, one per pod, once per monitor
|
|
488
|
+
# iteration: the first of a run opens a new cycle.
|
|
489
|
+
if (!last_pod_line) cycles++
|
|
490
|
+
last_pod_line = 1
|
|
491
|
+
remaining = lines_after + 1
|
|
492
|
+
if (redraw) {
|
|
493
|
+
clear_table()
|
|
494
|
+
draw_table()
|
|
495
|
+
}
|
|
496
|
+
if (!redraw) append_row(current_pod)
|
|
497
|
+
next
|
|
498
|
+
}
|
|
499
|
+
last_pod_line = 0
|
|
500
|
+
if ($0 ~ pattern) remaining = lines_after + 1
|
|
501
|
+
if (remaining > 0) {
|
|
502
|
+
if (is_trace($0)) {
|
|
503
|
+
remaining--
|
|
504
|
+
next
|
|
505
|
+
}
|
|
506
|
+
clear_table()
|
|
507
|
+
close_group()
|
|
508
|
+
put($0)
|
|
509
|
+
remaining--
|
|
510
|
+
draw_table()
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
END {
|
|
514
|
+
if (!handed_off && ready_pending()) hand_off()
|
|
515
|
+
close_group()
|
|
516
|
+
}
|
|
517
|
+
' <"$fifo_dir/merged" &
|
|
518
|
+
filter_pid=$!
|
|
519
|
+
|
|
520
|
+
# stderr is duplicated: on its own for the native error and stack trace, and
|
|
521
|
+
# into the merged stream so both the debug log and the filter see it in
|
|
522
|
+
# chronological order with stdout.
|
|
523
|
+
tee -a "$error_log" <"$fifo_dir/stderr" >"$fifo_dir/merged" &
|
|
524
|
+
stderr_pid=$!
|
|
525
|
+
|
|
526
|
+
"$@" >"$fifo_dir/merged" 2>"$fifo_dir/stderr" || status=$?
|
|
527
|
+
|
|
528
|
+
# Drain both readers before the paths are printed, or the trace can still be
|
|
529
|
+
# in flight. Bounded: a command that leaks a child holding a stream open must
|
|
530
|
+
# not hang the deployment, and by then everything read has been written.
|
|
531
|
+
run_quiet_drain "$stderr_pid"
|
|
532
|
+
run_quiet_drain "$filter_pid"
|
|
533
|
+
rm -rf "$fifo_dir"
|
|
534
|
+
|
|
535
|
+
# A deployment can fail without the command failing. The in-pod lifecycle latches
|
|
536
|
+
# `container-status=error` and deliberately does not crash the container, so a step that
|
|
537
|
+
# reported a fatal runtime state can still exit 0 — and a green step here is a green
|
|
538
|
+
# GitHub Actions job on a deployment that never came up. The latch the filter recorded is
|
|
539
|
+
# therefore promoted to a failure exit of its own.
|
|
540
|
+
fatal=$(cat "$fail_flag" 2>/dev/null) || true
|
|
541
|
+
rm -f "$fail_flag"
|
|
542
|
+
if [ "$status" -eq 0 ] && [ -n "$fatal" ]; then
|
|
543
|
+
status=1
|
|
544
|
+
printf '%s✖ %s reported a fatal runtime state but exited 0 (%s)%s\n' \
|
|
545
|
+
"$RUN_QUIET_RED" "$label" "$fatal" "$RUN_QUIET_RESET" >&2
|
|
546
|
+
fi
|
|
547
|
+
|
|
548
|
+
if [ "$status" -ne 0 ]; then
|
|
549
|
+
run_quiet_error_trace "$debug_log" "$error_log"
|
|
550
|
+
# One line of why, never the trace: the filter drops trace lines from the window.
|
|
551
|
+
reason=$(grep -a -m1 -E '^[A-Za-z]*Error: |reported runtime status=' "$debug_log" 2>/dev/null | head -1) || true
|
|
552
|
+
printf '%s✖ %s failed (exit %s)%s\n' "$RUN_QUIET_RED" "$label" "$status" "$RUN_QUIET_RESET" >&2
|
|
553
|
+
[ -n "$reason" ] && printf '%s reason: %s%s\n' "$RUN_QUIET_RED" "$reason" "$RUN_QUIET_RESET" >&2
|
|
554
|
+
printf '%s error trace: %s\n debug log: %s%s\n' \
|
|
555
|
+
"$RUN_QUIET_RED" "$error_log" "$debug_log" "$RUN_QUIET_RESET" >&2
|
|
556
|
+
return "$status"
|
|
557
|
+
fi
|
|
558
|
+
|
|
559
|
+
rm -f "$debug_log" "$error_log"
|
|
560
|
+
|
|
561
|
+
return "$status"
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
# Appends the failing part of the merged log to the error trace, so the trace ends
|
|
565
|
+
# with the error rather than with whatever last wrote to stderr. Cuts from the first
|
|
566
|
+
# error marker; with no marker the tail stands in, which is where a logger-only
|
|
567
|
+
# failure reports itself.
|
|
568
|
+
run_quiet_error_trace() {
|
|
569
|
+
local debug_log="$1"
|
|
570
|
+
local error_log="$2"
|
|
571
|
+
local tail_lines="${3:-40}"
|
|
572
|
+
local first
|
|
573
|
+
|
|
574
|
+
# grep exits 1 when it matches nothing, and every deploy script runs under `set -e` with
|
|
575
|
+
# `pipefail`: unguarded, a failing step whose log carries no marker aborted this function
|
|
576
|
+
# before run_quiet could print the exit code and the two log paths, and the tail fallback
|
|
577
|
+
# below was unreachable. The no-match case is the fallback's trigger, not an error.
|
|
578
|
+
first=$(grep -a -n -m1 -E 'Error:|Error \[|^[[:space:]]+at |✖' "$debug_log" 2>/dev/null | cut -d: -f1) || true
|
|
579
|
+
|
|
580
|
+
printf -- '--- error trace (from merged log) ---\n' >>"$error_log"
|
|
581
|
+
if [ -n "$first" ]; then
|
|
582
|
+
tail -n "+$first" "$debug_log" >>"$error_log"
|
|
583
|
+
else
|
|
584
|
+
tail -n "$tail_lines" "$debug_log" >>"$error_log"
|
|
585
|
+
fi
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
run_quiet_drain() {
|
|
589
|
+
local pid="$1"
|
|
590
|
+
|
|
591
|
+
timeout 10 tail --pid="$pid" -f /dev/null 2>/dev/null || true
|
|
592
|
+
kill "$pid" 2>/dev/null || true
|
|
593
|
+
wait "$pid" 2>/dev/null || true
|
|
594
|
+
}
|