smbcloud-cli 0.6.2__tar.gz → 0.7.0__tar.gz
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.
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/Cargo.lock +17 -17
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/Cargo.toml +12 -12
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/PKG-INFO +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy_rust.rs +378 -27
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_migrate.rs +1 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/deploy_config.rs +4 -2
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/project.rs +10 -3
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-network/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-utils/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/xcrs/Cargo.toml +1 -1
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/cli.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/forgot/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/login/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/login/process.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/logout/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/me/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/signup/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/account/signup/process.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ci.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cli/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/auth_app.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/cli.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/process.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/render.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/request.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-auth/url_builder.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/config.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/git.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy_nextjs_ssr.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy_rails.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy_static_site.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy_swift.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/remote_messages.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/setup.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/setup_create_new_project.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/setup_project.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/setup_select_project.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-mail/cli.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-mail/current_project.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-mail/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-mail/process.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-mail/render.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-mail/send.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/controlkit.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/interface.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/main.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/mcp.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/mcp_xcrs.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/cli.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/crud_create.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/crud_delete.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/crud_read.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/crud_update.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/deploy_target.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/deployment.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/project/process.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/session_config.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/cli.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/process.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/render.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/request.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/tenant_client.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/tenant/url_builder.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/token/clear_smb_token.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/token/get_smb_token.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/token/is_logged_in.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/token/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/token/smb_token_file_path.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/confirm_dialog.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/deployment_detail_view.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/deployment_table.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/me_view.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/plain.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/project_detail_view.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/project_table.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/prompt.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/reporter.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/ui/theme.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/.gitignore +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/check_email.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/login.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/logout.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/me.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/oauth/get_account_status.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/oauth/get_consent_url.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/oauth/get_profile.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/oauth/get_token.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/oauth/mod.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/oauth/provider.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/remove.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/resend_email_verification.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/resend_reset_password_instruction.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/reset_password.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-auth/src/signup.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/build.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/error.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/known_hosts.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/report.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/runner.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-deploy/src/transport.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/src/client.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/src/client_credentials.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/src/error.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/src/message.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-email-sdk/src/smbcloud_email_sdk.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/src/mail_app.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/src/mail_inbox.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/src/mail_message.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/src/request.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/src/smbcloud_mail.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-mail/src/url_builder.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/account.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/app_auth.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/deploy_config_update.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/error_codes.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/forgot.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/frontend_app.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/login.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/mail.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/oauth.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/repository.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/reset_password_response.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/runner.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/signup.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-model/src/tenant.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-network/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-network/src/environment.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-network/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-network/src/network.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking/src/constants.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking/src/smb_client.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_deploy_repo_create.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_frontend_app_create.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_frontend_app_deploy_config.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_frontend_app_read.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_frontend_app_update_deploy_config.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_create.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_delete.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_deployment_create.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_deployment_read.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_deployment_update.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_read.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/crud_project_update.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/request.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-networking-project/src/url_builder.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-utils/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-utils/src/config.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-utils/src/lib.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/smbcloud-utils/src/write_config.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/xcrs/README.md +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/xcrs/src/main.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/xcrs/src/mcp.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/xcrs/src/xcrs.rs +0 -0
- {smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/pyproject.toml +0 -0
|
@@ -2516,7 +2516,7 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
|
|
2516
2516
|
|
|
2517
2517
|
[[package]]
|
|
2518
2518
|
name = "smbcloud-auth"
|
|
2519
|
-
version = "0.
|
|
2519
|
+
version = "0.7.0"
|
|
2520
2520
|
dependencies = [
|
|
2521
2521
|
"log",
|
|
2522
2522
|
"reqwest",
|
|
@@ -2531,7 +2531,7 @@ dependencies = [
|
|
|
2531
2531
|
|
|
2532
2532
|
[[package]]
|
|
2533
2533
|
name = "smbcloud-auth-sdk"
|
|
2534
|
-
version = "0.
|
|
2534
|
+
version = "0.7.0"
|
|
2535
2535
|
dependencies = [
|
|
2536
2536
|
"base64 0.22.1",
|
|
2537
2537
|
"reqwest",
|
|
@@ -2546,7 +2546,7 @@ dependencies = [
|
|
|
2546
2546
|
|
|
2547
2547
|
[[package]]
|
|
2548
2548
|
name = "smbcloud-auth-sdk-py"
|
|
2549
|
-
version = "0.
|
|
2549
|
+
version = "0.7.0"
|
|
2550
2550
|
dependencies = [
|
|
2551
2551
|
"pyo3",
|
|
2552
2552
|
"pythonize",
|
|
@@ -2560,7 +2560,7 @@ dependencies = [
|
|
|
2560
2560
|
|
|
2561
2561
|
[[package]]
|
|
2562
2562
|
name = "smbcloud-auth-sdk-wasm"
|
|
2563
|
-
version = "0.
|
|
2563
|
+
version = "0.7.0"
|
|
2564
2564
|
dependencies = [
|
|
2565
2565
|
"serde-wasm-bindgen",
|
|
2566
2566
|
"smbcloud-auth-sdk",
|
|
@@ -2573,7 +2573,7 @@ dependencies = [
|
|
|
2573
2573
|
|
|
2574
2574
|
[[package]]
|
|
2575
2575
|
name = "smbcloud-cli"
|
|
2576
|
-
version = "0.
|
|
2576
|
+
version = "0.7.0"
|
|
2577
2577
|
dependencies = [
|
|
2578
2578
|
"anyhow",
|
|
2579
2579
|
"chrono",
|
|
@@ -2621,7 +2621,7 @@ dependencies = [
|
|
|
2621
2621
|
|
|
2622
2622
|
[[package]]
|
|
2623
2623
|
name = "smbcloud-deploy"
|
|
2624
|
-
version = "0.
|
|
2624
|
+
version = "0.7.0"
|
|
2625
2625
|
dependencies = [
|
|
2626
2626
|
"anyhow",
|
|
2627
2627
|
"serde_json",
|
|
@@ -2634,7 +2634,7 @@ dependencies = [
|
|
|
2634
2634
|
|
|
2635
2635
|
[[package]]
|
|
2636
2636
|
name = "smbcloud-email-sdk"
|
|
2637
|
-
version = "0.
|
|
2637
|
+
version = "0.7.0"
|
|
2638
2638
|
dependencies = [
|
|
2639
2639
|
"anyhow",
|
|
2640
2640
|
"log",
|
|
@@ -2649,7 +2649,7 @@ dependencies = [
|
|
|
2649
2649
|
|
|
2650
2650
|
[[package]]
|
|
2651
2651
|
name = "smbcloud-gresiq"
|
|
2652
|
-
version = "0.
|
|
2652
|
+
version = "0.7.0"
|
|
2653
2653
|
dependencies = [
|
|
2654
2654
|
"native-tls",
|
|
2655
2655
|
"postgres-native-tls",
|
|
@@ -2663,7 +2663,7 @@ dependencies = [
|
|
|
2663
2663
|
|
|
2664
2664
|
[[package]]
|
|
2665
2665
|
name = "smbcloud-gresiq-sdk"
|
|
2666
|
-
version = "0.
|
|
2666
|
+
version = "0.7.0"
|
|
2667
2667
|
dependencies = [
|
|
2668
2668
|
"anyhow",
|
|
2669
2669
|
"log",
|
|
@@ -2677,7 +2677,7 @@ dependencies = [
|
|
|
2677
2677
|
|
|
2678
2678
|
[[package]]
|
|
2679
2679
|
name = "smbcloud-mail"
|
|
2680
|
-
version = "0.
|
|
2680
|
+
version = "0.7.0"
|
|
2681
2681
|
dependencies = [
|
|
2682
2682
|
"reqwest",
|
|
2683
2683
|
"serde",
|
|
@@ -2689,7 +2689,7 @@ dependencies = [
|
|
|
2689
2689
|
|
|
2690
2690
|
[[package]]
|
|
2691
2691
|
name = "smbcloud-model"
|
|
2692
|
-
version = "0.
|
|
2692
|
+
version = "0.7.0"
|
|
2693
2693
|
dependencies = [
|
|
2694
2694
|
"chrono",
|
|
2695
2695
|
"log",
|
|
@@ -2705,7 +2705,7 @@ dependencies = [
|
|
|
2705
2705
|
|
|
2706
2706
|
[[package]]
|
|
2707
2707
|
name = "smbcloud-network"
|
|
2708
|
-
version = "0.
|
|
2708
|
+
version = "0.7.0"
|
|
2709
2709
|
dependencies = [
|
|
2710
2710
|
"clap 4.6.6",
|
|
2711
2711
|
"log",
|
|
@@ -2718,7 +2718,7 @@ dependencies = [
|
|
|
2718
2718
|
|
|
2719
2719
|
[[package]]
|
|
2720
2720
|
name = "smbcloud-networking"
|
|
2721
|
-
version = "0.
|
|
2721
|
+
version = "0.7.0"
|
|
2722
2722
|
dependencies = [
|
|
2723
2723
|
"smbcloud-network",
|
|
2724
2724
|
"url-builder",
|
|
@@ -2726,7 +2726,7 @@ dependencies = [
|
|
|
2726
2726
|
|
|
2727
2727
|
[[package]]
|
|
2728
2728
|
name = "smbcloud-networking-project"
|
|
2729
|
-
version = "0.
|
|
2729
|
+
version = "0.7.0"
|
|
2730
2730
|
dependencies = [
|
|
2731
2731
|
"anyhow",
|
|
2732
2732
|
"async-trait",
|
|
@@ -2744,11 +2744,11 @@ dependencies = [
|
|
|
2744
2744
|
|
|
2745
2745
|
[[package]]
|
|
2746
2746
|
name = "smbcloud-s6n"
|
|
2747
|
-
version = "0.
|
|
2747
|
+
version = "0.7.0"
|
|
2748
2748
|
|
|
2749
2749
|
[[package]]
|
|
2750
2750
|
name = "smbcloud-utils"
|
|
2751
|
-
version = "0.
|
|
2751
|
+
version = "0.7.0"
|
|
2752
2752
|
dependencies = [
|
|
2753
2753
|
"anyhow",
|
|
2754
2754
|
"dirs",
|
|
@@ -3973,7 +3973,7 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
|
|
|
3973
3973
|
|
|
3974
3974
|
[[package]]
|
|
3975
3975
|
name = "xcrs"
|
|
3976
|
-
version = "0.
|
|
3976
|
+
version = "0.7.0"
|
|
3977
3977
|
dependencies = [
|
|
3978
3978
|
"anyhow",
|
|
3979
3979
|
"base64 0.22.1",
|
|
@@ -29,17 +29,17 @@ schemars = "1"
|
|
|
29
29
|
serde = "1"
|
|
30
30
|
serde_json = "1.0.82"
|
|
31
31
|
serde_repr = "0.1"
|
|
32
|
-
smbcloud-auth = { version = "0.
|
|
33
|
-
smbcloud-auth-sdk = { version = "0.
|
|
34
|
-
smbcloud-deploy = { version = "0.
|
|
35
|
-
smbcloud-email-sdk = { version = "0.
|
|
36
|
-
smbcloud-gresiq-sdk = { version = "0.
|
|
37
|
-
smbcloud-mail = { version = "0.
|
|
38
|
-
smbcloud-model = { version = "0.
|
|
39
|
-
smbcloud-network = { version = "0.
|
|
40
|
-
smbcloud-networking = { version = "0.
|
|
41
|
-
smbcloud-networking-project = { version = "0.
|
|
42
|
-
smbcloud-utils = { version = "0.
|
|
32
|
+
smbcloud-auth = { version = "0.7.0", path = "crates/smbcloud-auth" }
|
|
33
|
+
smbcloud-auth-sdk = { version = "0.7.0", path = "crates/smbcloud-auth-sdk" }
|
|
34
|
+
smbcloud-deploy = { version = "0.7.0", path = "crates/smbcloud-deploy" }
|
|
35
|
+
smbcloud-email-sdk = { version = "0.7.0", path = "crates/smbcloud-email-sdk" }
|
|
36
|
+
smbcloud-gresiq-sdk = { version = "0.7.0", path = "crates/smbcloud-gresiq-sdk" }
|
|
37
|
+
smbcloud-mail = { version = "0.7.0", path = "crates/smbcloud-mail" }
|
|
38
|
+
smbcloud-model = { version = "0.7.0", path = "crates/smbcloud-model" }
|
|
39
|
+
smbcloud-network = { version = "0.7.0", path = "crates/smbcloud-network" }
|
|
40
|
+
smbcloud-networking = { version = "0.7.0", path = "crates/smbcloud-networking" }
|
|
41
|
+
smbcloud-networking-project = { version = "0.7.0", path = "crates/smbcloud-networking-project" }
|
|
42
|
+
smbcloud-utils = { version = "0.7.0", path = "crates/smbcloud-utils" }
|
|
43
43
|
spinners = "4.1.0"
|
|
44
44
|
strum = "0.27"
|
|
45
45
|
strum_macros = "0.27"
|
|
@@ -56,4 +56,4 @@ tsync = "2"
|
|
|
56
56
|
uniffi = "0.31"
|
|
57
57
|
url-builder = "0.1.1"
|
|
58
58
|
wasm-bindgen = "0.2"
|
|
59
|
-
xcrs = { version = "0.
|
|
59
|
+
xcrs = { version = "0.7.0", path = "crates/xcrs" }
|
{smbcloud_cli-0.6.2 → smbcloud_cli-0.7.0}/crates/cli/src/cloud-deploy/process_deploy_rust.rs
RENAMED
|
@@ -38,6 +38,13 @@ const DEFAULT_RUST_TARGET: &str = "x86_64-unknown-linux-gnu";
|
|
|
38
38
|
/// - `source` — local crate directory (defaults to current directory)
|
|
39
39
|
/// - `binary_name` — binary filename to upload; falls back to Cargo package name
|
|
40
40
|
/// - `rust_target` — local cross-compilation target triple; defaults to `x86_64-unknown-linux-gnu`
|
|
41
|
+
/// - `process_manager` — `"nohup"` (default) or `"systemd"`; systemd restarts
|
|
42
|
+
/// `<binary_name>.service` with `systemctl --user` (see `resolve_supervisor`)
|
|
43
|
+
/// - `port`, `health_path` — when both are set, the deploy polls
|
|
44
|
+
/// `http://127.0.0.1:<port><health_path>` after the restart
|
|
45
|
+
///
|
|
46
|
+
/// The binary is uploaded as `<binary>.new`, the live one is kept as
|
|
47
|
+
/// `<binary>.previous`, and a failed check restores it.
|
|
41
48
|
pub async fn process_deploy_rust(env: Environment, config: Config) -> Result<CommandResult> {
|
|
42
49
|
let deploy_start = std::time::Instant::now();
|
|
43
50
|
|
|
@@ -56,6 +63,9 @@ pub async fn process_deploy_rust(env: Environment, config: Config) -> Result<Com
|
|
|
56
63
|
))));
|
|
57
64
|
}
|
|
58
65
|
|
|
66
|
+
let supervisor = resolve_supervisor(config.project.process_manager.as_deref())?;
|
|
67
|
+
let health_url =
|
|
68
|
+
resolve_health_url(config.project.port, config.project.health_path.as_deref())?;
|
|
59
69
|
let binary_name = resolve_binary_name(&config, source_dir)?;
|
|
60
70
|
let rust_target = config
|
|
61
71
|
.project
|
|
@@ -160,7 +170,10 @@ pub async fn process_deploy_rust(env: Environment, config: Config) -> Result<Com
|
|
|
160
170
|
} else {
|
|
161
171
|
format!("{}/", remote_path)
|
|
162
172
|
};
|
|
163
|
-
let destination = format!(
|
|
173
|
+
let destination = format!(
|
|
174
|
+
"git@{}:{}{}.new",
|
|
175
|
+
rsync_host, remote_with_slash, binary_name
|
|
176
|
+
);
|
|
164
177
|
let binary_path_str = binary_path.to_string_lossy().into_owned();
|
|
165
178
|
|
|
166
179
|
let binary_size = fs::metadata(&binary_path).map(|m| m.len()).unwrap_or(0);
|
|
@@ -229,7 +242,8 @@ pub async fn process_deploy_rust(env: Environment, config: Config) -> Result<Com
|
|
|
229
242
|
),
|
|
230
243
|
);
|
|
231
244
|
|
|
232
|
-
let deploy_script =
|
|
245
|
+
let deploy_script =
|
|
246
|
+
build_remote_start_script(remote_path, &binary_name, supervisor, health_url.as_deref());
|
|
233
247
|
let ssh_output = run_remote_script(
|
|
234
248
|
&identity_file_str,
|
|
235
249
|
&known_hosts_file,
|
|
@@ -247,6 +261,12 @@ pub async fn process_deploy_rust(env: Environment, config: Config) -> Result<Com
|
|
|
247
261
|
fail_message("Launch failed")
|
|
248
262
|
);
|
|
249
263
|
print_output_details(&ssh_output);
|
|
264
|
+
if let Some(line) = String::from_utf8_lossy(&ssh_output.stdout)
|
|
265
|
+
.lines()
|
|
266
|
+
.find(|line| line.starts_with("Rolled back"))
|
|
267
|
+
{
|
|
268
|
+
eprintln!("{}", line);
|
|
269
|
+
}
|
|
250
270
|
mark_failed(
|
|
251
271
|
&deploy_ref,
|
|
252
272
|
&created_deployment,
|
|
@@ -474,9 +494,71 @@ echo "Prepared $APP_PATH"
|
|
|
474
494
|
)
|
|
475
495
|
}
|
|
476
496
|
|
|
477
|
-
|
|
478
|
-
|
|
497
|
+
/// How the service is stopped and started on the server.
|
|
498
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
499
|
+
enum Supervisor {
|
|
500
|
+
/// Kill the old process, start the new one with `nohup`.
|
|
501
|
+
Nohup,
|
|
502
|
+
/// `systemctl --user restart <binary_name>.service`.
|
|
503
|
+
Systemd,
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/// Maps `process_manager` to a [`Supervisor`] (matched case-insensitively).
|
|
507
|
+
/// `None`, `""` and `"nohup"` keep the original behaviour. Any other value is a
|
|
508
|
+
/// hard error: a typo like `system` must not start a nohup process next to a
|
|
509
|
+
/// systemd-owned one that already holds the port.
|
|
510
|
+
fn resolve_supervisor(process_manager: Option<&str>) -> Result<Supervisor> {
|
|
511
|
+
match process_manager.map(str::trim) {
|
|
512
|
+
None | Some("") => Ok(Supervisor::Nohup),
|
|
513
|
+
Some(m) if m.eq_ignore_ascii_case("nohup") => Ok(Supervisor::Nohup),
|
|
514
|
+
Some(m) if m.eq_ignore_ascii_case("systemd") => Ok(Supervisor::Systemd),
|
|
515
|
+
Some(other) => Err(anyhow!(fail_message(&format!(
|
|
516
|
+
"Unknown process_manager '{other}' in .smb/config.toml. \
|
|
517
|
+
Expected \"nohup\" (default) or \"systemd\"."
|
|
518
|
+
)))),
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/// Builds the URL the remote script polls after the restart. `None` unless both
|
|
523
|
+
/// `port` and `health_path` are set. The path ends up in a shell script, so it
|
|
524
|
+
/// is limited to URL-path characters, and every `%` must start a valid
|
|
525
|
+
/// percent-escape.
|
|
526
|
+
fn resolve_health_url(port: Option<u16>, health_path: Option<&str>) -> Result<Option<String>> {
|
|
527
|
+
let Some(path) = health_path.map(str::trim).filter(|path| !path.is_empty()) else {
|
|
528
|
+
return Ok(None);
|
|
529
|
+
};
|
|
530
|
+
let bytes = path.as_bytes();
|
|
531
|
+
let valid = path.starts_with('/')
|
|
532
|
+
&& path
|
|
533
|
+
.chars()
|
|
534
|
+
.all(|c| c.is_ascii_alphanumeric() || matches!(c, '/' | '-' | '_' | '.' | '~' | '%'))
|
|
535
|
+
&& bytes.iter().enumerate().all(|(i, &b)| {
|
|
536
|
+
b != b'%'
|
|
537
|
+
|| bytes
|
|
538
|
+
.get(i + 1..i + 3)
|
|
539
|
+
.is_some_and(|hex| hex.iter().all(u8::is_ascii_hexdigit))
|
|
540
|
+
});
|
|
541
|
+
if !valid {
|
|
542
|
+
return Err(anyhow!(fail_message(&format!(
|
|
543
|
+
"Invalid health_path '{path}' in .smb/config.toml. \
|
|
544
|
+
It must start with '/' and contain only letters, digits and / - _ . ~ %; \
|
|
545
|
+
each % must be followed by two hex digits."
|
|
546
|
+
))));
|
|
547
|
+
}
|
|
548
|
+
Ok(port.map(|port| format!("http://127.0.0.1:{port}{path}")))
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/// Remote script: swap the uploaded `<binary>.new` into place (keeping the live
|
|
552
|
+
/// one as `<binary>.previous`), restart, verify, and roll back on failure.
|
|
553
|
+
fn build_remote_start_script(
|
|
554
|
+
remote_path: &str,
|
|
555
|
+
binary_name: &str,
|
|
556
|
+
supervisor: Supervisor,
|
|
557
|
+
health_url: Option<&str>,
|
|
558
|
+
) -> String {
|
|
559
|
+
let mut script = format!(
|
|
479
560
|
r#"set -e
|
|
561
|
+
exec 2>&1
|
|
480
562
|
APP_PATH={remote_path}
|
|
481
563
|
PROCESS_NAME={binary_name}
|
|
482
564
|
|
|
@@ -492,41 +574,166 @@ fi
|
|
|
492
574
|
|
|
493
575
|
cd "$APP_PATH"
|
|
494
576
|
|
|
495
|
-
if [ ! -f "$PROCESS_NAME" ]; then
|
|
496
|
-
echo "Error: $PROCESS_NAME does not exist in $APP_PATH."
|
|
577
|
+
if [ ! -f "$PROCESS_NAME.new" ]; then
|
|
578
|
+
echo "Error: $PROCESS_NAME.new does not exist in $APP_PATH."
|
|
497
579
|
exit 1
|
|
498
580
|
fi
|
|
499
581
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
582
|
+
"#,
|
|
583
|
+
remote_path = shell_single_quote(remote_path),
|
|
584
|
+
binary_name = shell_single_quote(binary_name),
|
|
585
|
+
);
|
|
586
|
+
script.push_str(&restart_section(supervisor));
|
|
587
|
+
script.push_str(&verify_section(supervisor, health_url));
|
|
588
|
+
script.push_str(swap_section());
|
|
589
|
+
script.push_str(
|
|
590
|
+
r#"if restart_service && check_service; then
|
|
591
|
+
started
|
|
592
|
+
echo "Done."
|
|
593
|
+
exit 0
|
|
594
|
+
fi
|
|
503
595
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
596
|
+
echo "Error: $PROCESS_NAME failed its check after the restart."
|
|
597
|
+
show_logs
|
|
598
|
+
if [ -f "$PROCESS_NAME.previous" ]; then
|
|
599
|
+
echo "Rolling back to the previous binary..."
|
|
600
|
+
cp -p "$PROCESS_NAME.previous" "$PROCESS_NAME.rollback"
|
|
601
|
+
mv -f "$PROCESS_NAME.rollback" "$PROCESS_NAME"
|
|
602
|
+
if restart_service && check_service; then
|
|
603
|
+
echo "Rolled back to the previous $PROCESS_NAME, which is serving again."
|
|
604
|
+
else
|
|
605
|
+
echo "Rolled back to the previous $PROCESS_NAME, but it failed its check too."
|
|
511
606
|
fi
|
|
607
|
+
else
|
|
608
|
+
echo "No previous binary to roll back to."
|
|
609
|
+
fi
|
|
610
|
+
exit 1
|
|
611
|
+
"#,
|
|
612
|
+
);
|
|
613
|
+
script
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/// Keeps the live binary as `.previous` and moves `.new` into place.
|
|
617
|
+
fn swap_section() -> &'static str {
|
|
618
|
+
r#"if [ -f "$PROCESS_NAME" ]; then
|
|
619
|
+
cp -p "$PROCESS_NAME" "$PROCESS_NAME.previous"
|
|
512
620
|
fi
|
|
621
|
+
chmod +x "$PROCESS_NAME.new"
|
|
622
|
+
mv -f "$PROCESS_NAME.new" "$PROCESS_NAME"
|
|
513
623
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
624
|
+
"#
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/// Defines `restart_service`. The systemd variant also fails early, before the
|
|
628
|
+
/// swap, when the unit does not exist.
|
|
629
|
+
fn restart_section(supervisor: Supervisor) -> String {
|
|
630
|
+
match supervisor {
|
|
631
|
+
Supervisor::Nohup => r#"restart_service() {
|
|
632
|
+
PID=$(pidof "$PROCESS_NAME" 2>/dev/null || true)
|
|
633
|
+
if [ -n "$PID" ]; then
|
|
634
|
+
echo "Stopping $PROCESS_NAME ($PID)..."
|
|
635
|
+
kill "$PID" 2>/dev/null || true
|
|
636
|
+
sleep 2
|
|
637
|
+
if kill -0 "$PID" 2>/dev/null; then
|
|
638
|
+
echo "Force-killing $PROCESS_NAME ($PID)..."
|
|
639
|
+
kill -9 "$PID" 2>/dev/null || true
|
|
640
|
+
fi
|
|
641
|
+
fi
|
|
642
|
+
echo "Starting $PROCESS_NAME..."
|
|
643
|
+
nohup "./$PROCESS_NAME" >> "$APP_PATH/$PROCESS_NAME.log" 2>&1 &
|
|
644
|
+
}
|
|
517
645
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
646
|
+
"#
|
|
647
|
+
.to_owned(),
|
|
648
|
+
Supervisor::Systemd => r#"export XDG_RUNTIME_DIR="/run/user/$(id -u)"
|
|
649
|
+
UNIT="$PROCESS_NAME.service"
|
|
650
|
+
if ! systemctl --user cat "$UNIT" >/dev/null 2>&1; then
|
|
651
|
+
echo "Error: systemd --user unit $UNIT not found on the server."
|
|
652
|
+
echo "Create ~/.config/systemd/user/$UNIT and enable it (see the"
|
|
653
|
+
echo "smbcloud-deploy-rust guide, 'Process manager: systemd --user'),"
|
|
654
|
+
echo "or unset process_manager to use the default start. Then re-deploy."
|
|
521
655
|
exit 1
|
|
522
656
|
fi
|
|
523
657
|
|
|
524
|
-
|
|
525
|
-
echo "
|
|
658
|
+
restart_service() {
|
|
659
|
+
echo "Restarting $UNIT via systemd --user..."
|
|
660
|
+
systemctl --user restart "$UNIT"
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
"#
|
|
664
|
+
.to_owned(),
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/// Defines `check_service`, `started` and `show_logs`. The check polls the
|
|
669
|
+
/// health URL for up to 30 seconds when there is one, else looks for a live
|
|
670
|
+
/// process (`is-active` under systemd, `pidof` under nohup).
|
|
671
|
+
fn verify_section(supervisor: Supervisor, health_url: Option<&str>) -> String {
|
|
672
|
+
let mut section = String::new();
|
|
673
|
+
match health_url {
|
|
674
|
+
Some(url) => {
|
|
675
|
+
section.push_str(&format!("HEALTH_URL={}\n\n", shell_single_quote(url)));
|
|
676
|
+
section.push_str(
|
|
677
|
+
r#"check_service() {
|
|
678
|
+
echo "Waiting for $HEALTH_URL..."
|
|
679
|
+
i=0
|
|
680
|
+
while [ "$i" -lt 30 ]; do
|
|
681
|
+
if curl -fsS -o /dev/null --max-time 2 "$HEALTH_URL"; then
|
|
682
|
+
return 0
|
|
683
|
+
fi
|
|
684
|
+
i=$((i + 1))
|
|
685
|
+
sleep 1
|
|
686
|
+
done
|
|
687
|
+
return 1
|
|
688
|
+
}
|
|
689
|
+
|
|
526
690
|
"#,
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
None => section.push_str(match supervisor {
|
|
694
|
+
Supervisor::Systemd => {
|
|
695
|
+
r#"check_service() {
|
|
696
|
+
sleep 3
|
|
697
|
+
systemctl --user is-active "$UNIT" >/dev/null 2>&1
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
"#
|
|
701
|
+
}
|
|
702
|
+
Supervisor::Nohup => {
|
|
703
|
+
r#"check_service() {
|
|
704
|
+
sleep 1
|
|
705
|
+
[ -n "$(pidof "$PROCESS_NAME" 2>/dev/null || true)" ]
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
"#
|
|
709
|
+
}
|
|
710
|
+
}),
|
|
711
|
+
}
|
|
712
|
+
section.push_str(match supervisor {
|
|
713
|
+
Supervisor::Systemd => {
|
|
714
|
+
r#"started() {
|
|
715
|
+
echo "Started $PROCESS_NAME via $UNIT"
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
show_logs() {
|
|
719
|
+
journalctl --user -u "$UNIT" -n 20 --no-pager 2>&1 || true
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
"#
|
|
723
|
+
}
|
|
724
|
+
Supervisor::Nohup => {
|
|
725
|
+
r#"started() {
|
|
726
|
+
echo "Started $PROCESS_NAME as $(pidof "$PROCESS_NAME" 2>/dev/null || true)"
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
show_logs() {
|
|
730
|
+
tail -n 20 "$APP_PATH/$PROCESS_NAME.log" 2>&1 || true
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
"#
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
section
|
|
530
737
|
}
|
|
531
738
|
|
|
532
739
|
fn build_ssh_command(identity_file: &str, known_hosts_file: &NamedTempFile) -> String {
|
|
@@ -639,3 +846,147 @@ async fn mark_failed(
|
|
|
639
846
|
.await;
|
|
640
847
|
}
|
|
641
848
|
}
|
|
849
|
+
|
|
850
|
+
#[cfg(test)]
|
|
851
|
+
mod tests {
|
|
852
|
+
use super::*;
|
|
853
|
+
|
|
854
|
+
fn script(supervisor: Supervisor, health_url: Option<&str>) -> String {
|
|
855
|
+
build_remote_start_script("apps/my-app", "my-app", supervisor, health_url)
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
#[test]
|
|
859
|
+
fn resolve_supervisor_defaults_to_nohup() {
|
|
860
|
+
for pm in [
|
|
861
|
+
None,
|
|
862
|
+
Some(""),
|
|
863
|
+
Some("nohup"),
|
|
864
|
+
Some("NoHup"),
|
|
865
|
+
Some(" nohup "),
|
|
866
|
+
] {
|
|
867
|
+
assert_eq!(resolve_supervisor(pm).unwrap(), Supervisor::Nohup, "{pm:?}");
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
#[test]
|
|
872
|
+
fn resolve_supervisor_systemd_is_case_insensitive() {
|
|
873
|
+
for pm in ["systemd", "SystemD", " systemd "] {
|
|
874
|
+
assert_eq!(resolve_supervisor(Some(pm)).unwrap(), Supervisor::Systemd);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
#[test]
|
|
879
|
+
fn resolve_supervisor_rejects_unknown_value() {
|
|
880
|
+
for pm in ["system", "pm2", "supervisord"] {
|
|
881
|
+
let msg = resolve_supervisor(Some(pm)).unwrap_err().to_string();
|
|
882
|
+
assert!(msg.contains(pm), "names the offending value: {msg}");
|
|
883
|
+
assert!(msg.contains("nohup") && msg.contains("systemd"), "{msg}");
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
#[test]
|
|
888
|
+
fn systemd_script_restarts_the_user_unit() {
|
|
889
|
+
let s = script(Supervisor::Systemd, None);
|
|
890
|
+
assert!(s.contains("systemctl --user restart \"$UNIT\""));
|
|
891
|
+
assert!(s.contains("UNIT=\"$PROCESS_NAME.service\""));
|
|
892
|
+
assert!(s.contains("XDG_RUNTIME_DIR=\"/run/user/$(id -u)\""));
|
|
893
|
+
assert!(s.contains("systemctl --user is-active"));
|
|
894
|
+
assert!(!s.contains("nohup"));
|
|
895
|
+
assert!(!s.contains("kill"));
|
|
896
|
+
assert!(!s.contains("sudo"));
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
#[test]
|
|
900
|
+
fn nohup_script_keeps_the_pidof_flow() {
|
|
901
|
+
let s = script(Supervisor::Nohup, None);
|
|
902
|
+
assert!(s.contains("pidof"));
|
|
903
|
+
assert!(s.contains("nohup \"./$PROCESS_NAME\""));
|
|
904
|
+
assert!(!s.contains("systemctl"));
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
#[test]
|
|
908
|
+
fn both_scripts_back_up_and_swap_before_restarting() {
|
|
909
|
+
for supervisor in [Supervisor::Nohup, Supervisor::Systemd] {
|
|
910
|
+
let s = script(supervisor, None);
|
|
911
|
+
let backup = s
|
|
912
|
+
.find("cp -p \"$PROCESS_NAME\" \"$PROCESS_NAME.previous\"")
|
|
913
|
+
.unwrap();
|
|
914
|
+
let swap = s
|
|
915
|
+
.find("mv -f \"$PROCESS_NAME.new\" \"$PROCESS_NAME\"")
|
|
916
|
+
.unwrap();
|
|
917
|
+
let restart = s.find("if restart_service && check_service").unwrap();
|
|
918
|
+
assert!(backup < swap && swap < restart, "{supervisor:?}");
|
|
919
|
+
assert!(s.contains("Rolled back"), "{supervisor:?}");
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
#[test]
|
|
924
|
+
fn health_url_controls_the_curl_poll() {
|
|
925
|
+
for supervisor in [Supervisor::Nohup, Supervisor::Systemd] {
|
|
926
|
+
let with = script(supervisor, Some("http://127.0.0.1:8080/health"));
|
|
927
|
+
assert!(with.contains("curl -fsS"));
|
|
928
|
+
assert!(with.contains("HEALTH_URL='http://127.0.0.1:8080/health'"));
|
|
929
|
+
assert!(!script(supervisor, None).contains("curl"));
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
#[test]
|
|
934
|
+
fn health_url_needs_both_port_and_path() {
|
|
935
|
+
let url = resolve_health_url(Some(8080), Some("/health")).unwrap();
|
|
936
|
+
assert_eq!(url.as_deref(), Some("http://127.0.0.1:8080/health"));
|
|
937
|
+
assert_eq!(resolve_health_url(None, Some("/health")).unwrap(), None);
|
|
938
|
+
assert_eq!(resolve_health_url(Some(8080), None).unwrap(), None);
|
|
939
|
+
assert_eq!(resolve_health_url(Some(8080), Some("")).unwrap(), None);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
#[test]
|
|
943
|
+
fn health_path_validation_rejects_unsafe_values() {
|
|
944
|
+
for path in [
|
|
945
|
+
"health", "/a b", "/x;rm", "/$(id)", "/a'b", "/foo%ZZ", "/foo%", "/foo%2",
|
|
946
|
+
] {
|
|
947
|
+
assert!(
|
|
948
|
+
resolve_health_url(Some(8080), Some(path)).is_err(),
|
|
949
|
+
"{path}"
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
#[test]
|
|
955
|
+
fn health_path_accepts_valid_percent_escapes() {
|
|
956
|
+
let url = resolve_health_url(Some(8080), Some("/a%20b")).unwrap();
|
|
957
|
+
assert_eq!(url.as_deref(), Some("http://127.0.0.1:8080/a%20b"));
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
#[test]
|
|
961
|
+
fn binary_name_with_single_quote_is_quoted() {
|
|
962
|
+
let s = build_remote_start_script("apps/x", "a'b", Supervisor::Nohup, None);
|
|
963
|
+
assert!(s.contains("PROCESS_NAME='a'\"'\"'b'"));
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
#[test]
|
|
967
|
+
fn every_script_variant_is_valid_bash() {
|
|
968
|
+
for supervisor in [Supervisor::Nohup, Supervisor::Systemd] {
|
|
969
|
+
for health in [None, Some("http://127.0.0.1:8080/health")] {
|
|
970
|
+
let mut child = Command::new("bash")
|
|
971
|
+
.args(["-n", "-s"])
|
|
972
|
+
.stdin(Stdio::piped())
|
|
973
|
+
.stdout(Stdio::piped())
|
|
974
|
+
.stderr(Stdio::piped())
|
|
975
|
+
.spawn()
|
|
976
|
+
.expect("bash is available");
|
|
977
|
+
child
|
|
978
|
+
.stdin
|
|
979
|
+
.take()
|
|
980
|
+
.unwrap()
|
|
981
|
+
.write_all(script(supervisor, health).as_bytes())
|
|
982
|
+
.unwrap();
|
|
983
|
+
let out = child.wait_with_output().unwrap();
|
|
984
|
+
assert!(
|
|
985
|
+
out.status.success(),
|
|
986
|
+
"{supervisor:?} {health:?}: {}",
|
|
987
|
+
String::from_utf8_lossy(&out.stderr)
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|