splent-cli 1.10.0__tar.gz → 1.11.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.
- {splent_cli-1.10.0/src/splent_cli.egg-info → splent_cli-1.11.0}/PKG-INFO +1 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/pyproject.toml +6 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_infra.py +4 -12
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_migrate.py +1 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_seed.py +1 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/doctor.py +3 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_clone.py +46 -99
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_compile.py +1 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_env.py +1 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_install.py +21 -28
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_refine.py +2 -5
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_release.py +8 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_search.py +2 -6
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_upgrade.py +30 -14
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/lint.py +3 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/locust.py +2 -6
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_clean.py +3 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_create.py +1 -7
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_env.py +1 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_release.py +8 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_run.py +3 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_up.py +14 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/release/release_core.py +26 -4
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_add_feature.py +1 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/uvl/uvl_utils.py +1 -3
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/services/release.py +112 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/dynamic_imports.py +1 -3
- splent_cli-1.11.0/src/splent_cli/utils/git_url.py +221 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/integrity.py +4 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/io_utils.py +3 -1
- {splent_cli-1.10.0 → splent_cli-1.11.0/src/splent_cli.egg-info}/PKG-INFO +1 -1
- splent_cli-1.10.0/src/splent_cli/utils/git_url.py +0 -82
- {splent_cli-1.10.0 → splent_cli-1.11.0}/LICENSE +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/README.md +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/setup.cfg +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/__main__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/cli.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_clear.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_orphans.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_outdated.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_prune.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_size.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_status.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_usage.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/cache/cache_versions.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_deps.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_docker.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_env.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_features.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_github.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_product.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_pypi.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/check/check_pyproject.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/clear/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/clear/clear_build.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/clear/clear_log.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/clear/clear_uploads.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/command/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/command/command_create.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/coverage.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_console.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_dump.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_reset.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_restore.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_rollback.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_status.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/database/db_upgrade.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/env/env_list.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/env/env_set.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/env/env_show.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/export/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/export/export_puml.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_add.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_attach.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_clean.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_compat.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_contract.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_create.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_delete.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_detach.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_discard.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_drift.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_fork.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_git.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_hook_add.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_hook_remove.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_hooks.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_impact.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_inject_config.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_list.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_order.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_outdated.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_pin.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_pip_install.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_pull.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_remove.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_rename.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_status.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_sync_template.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_test.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_translate.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_unlock.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_versions.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/feature/feature_xray.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_auto_require.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_build.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_commands.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_config.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_configure.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_console.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_containers.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_deploy.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_derive.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_deselect.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_down.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_drift.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_list.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_logs.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_missing.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_port.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_resolve.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_restart.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_routes.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_select.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_shell.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_signals.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_sync_template.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_test.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/product/product_validate.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/release/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/selenium.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_add_constraints.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_configurations.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_create.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_deps.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_features.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_fetch.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_info.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_list.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/spl/spl_utils.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/tokens_setup.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/commands/version.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/services/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/services/compose.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/services/context.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/services/preflight.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/__init__.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/cache_utils.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/command_loader.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/contract_freshness.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/db_utils.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/decorators.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/feature_installer.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/feature_utils.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/lifecycle.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/manifest.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/path_utils.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/proc.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli/utils/template_drift.py +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli.egg-info/SOURCES.txt +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli.egg-info/dependency_links.txt +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli.egg-info/entry_points.txt +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli.egg-info/requires.txt +0 -0
- {splent_cli-1.10.0 → splent_cli-1.11.0}/src/splent_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: splent_cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11.0
|
|
4
4
|
Summary: SPLENT-CLI is a CLI to be able to work on your development more easily.
|
|
5
5
|
Author-email: DiversoLab <diversolab@us.es>
|
|
6
6
|
Project-URL: Homepage, https://github.com/diverso-lab/splent_cli
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "splent_cli"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.11.0"
|
|
8
8
|
description = "SPLENT-CLI is a CLI to be able to work on your development more easily."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -63,8 +63,11 @@ where = ["src"]
|
|
|
63
63
|
testpaths = ["tests"]
|
|
64
64
|
pythonpath = ["src"]
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
line
|
|
66
|
+
# Canonical formatter/linter is Ruff (`splent lint` runs `ruff check` +
|
|
67
|
+
# `ruff format`). Ruff's default line length (88) is the project standard;
|
|
68
|
+
# set explicitly here so it is unambiguous.
|
|
69
|
+
[tool.ruff]
|
|
70
|
+
line-length = 88
|
|
68
71
|
|
|
69
72
|
[project.urls]
|
|
70
73
|
Homepage = "https://github.com/diverso-lab/splent_cli"
|
|
@@ -209,9 +209,7 @@ def check_infra():
|
|
|
209
209
|
click.echo(click.style(" Networks", bold=True))
|
|
210
210
|
required_networks: set[str] = set()
|
|
211
211
|
for label, cf in compose_files:
|
|
212
|
-
result = _run(
|
|
213
|
-
["docker", "compose", "-f", cf, "config", "--format", "json"]
|
|
214
|
-
)
|
|
212
|
+
result = _run(["docker", "compose", "-f", cf, "config", "--format", "json"])
|
|
215
213
|
if result.returncode != 0:
|
|
216
214
|
continue
|
|
217
215
|
try:
|
|
@@ -242,9 +240,7 @@ def check_infra():
|
|
|
242
240
|
build_count = 0
|
|
243
241
|
for label, cf in compose_files:
|
|
244
242
|
docker_dir = os.path.dirname(cf)
|
|
245
|
-
result = _run(
|
|
246
|
-
["docker", "compose", "-f", cf, "config", "--format", "json"]
|
|
247
|
-
)
|
|
243
|
+
result = _run(["docker", "compose", "-f", cf, "config", "--format", "json"])
|
|
248
244
|
if result.returncode != 0:
|
|
249
245
|
continue
|
|
250
246
|
try:
|
|
@@ -282,9 +278,7 @@ def check_infra():
|
|
|
282
278
|
services_depended_on: dict[str, str] = {} # depended_svc -> by_svc
|
|
283
279
|
|
|
284
280
|
for label, cf in compose_files:
|
|
285
|
-
result = _run(
|
|
286
|
-
["docker", "compose", "-f", cf, "config", "--format", "json"]
|
|
287
|
-
)
|
|
281
|
+
result = _run(["docker", "compose", "-f", cf, "config", "--format", "json"])
|
|
288
282
|
if result.returncode != 0:
|
|
289
283
|
continue
|
|
290
284
|
try:
|
|
@@ -321,9 +315,7 @@ def check_infra():
|
|
|
321
315
|
click.echo(click.style(" Volumes", bold=True))
|
|
322
316
|
all_volumes: dict[str, list[str]] = {} # vol_name -> [labels]
|
|
323
317
|
for label, cf in compose_files:
|
|
324
|
-
result = _run(
|
|
325
|
-
["docker", "compose", "-f", cf, "config", "--format", "json"]
|
|
326
|
-
)
|
|
318
|
+
result = _run(["docker", "compose", "-f", cf, "config", "--format", "json"])
|
|
327
319
|
if result.returncode != 0:
|
|
328
320
|
continue
|
|
329
321
|
try:
|
|
@@ -75,9 +75,7 @@ def db_migrate(feature, message, empty):
|
|
|
75
75
|
and kept so you can write ``upgrade()``/``downgrade()`` by hand.
|
|
76
76
|
"""
|
|
77
77
|
if empty and not feature:
|
|
78
|
-
click.echo(
|
|
79
|
-
click.style("❌ --empty requires a FEATURE argument.", fg="red")
|
|
80
|
-
)
|
|
78
|
+
click.echo(click.style("❌ --empty requires a FEATURE argument.", fg="red"))
|
|
81
79
|
raise SystemExit(1)
|
|
82
80
|
|
|
83
81
|
if feature:
|
|
@@ -179,9 +179,7 @@ def db_seed(reset, yes, module):
|
|
|
179
179
|
break
|
|
180
180
|
except Exception as e:
|
|
181
181
|
click.echo(
|
|
182
|
-
click.style(
|
|
183
|
-
f"❌ Error in {seeder.__class__.__name__}: {e}", fg="red"
|
|
184
|
-
)
|
|
182
|
+
click.style(f"❌ Error in {seeder.__class__.__name__}: {e}", fg="red")
|
|
185
183
|
)
|
|
186
184
|
success = False
|
|
187
185
|
break
|
|
@@ -68,7 +68,9 @@ def _check_workspace_precondition():
|
|
|
68
68
|
wd = os.getenv("WORKING_DIR")
|
|
69
69
|
workspace = wd or os.getcwd()
|
|
70
70
|
if not wd:
|
|
71
|
-
problems.append(
|
|
71
|
+
problems.append(
|
|
72
|
+
"WORKING_DIR is not set (falling back to the current directory)"
|
|
73
|
+
)
|
|
72
74
|
elif not os.path.isdir(wd):
|
|
73
75
|
problems.append(f"WORKING_DIR points to a missing directory: {wd}")
|
|
74
76
|
|
|
@@ -6,7 +6,7 @@ import click
|
|
|
6
6
|
from splent_cli.services import context
|
|
7
7
|
from splent_cli.utils.cache_utils import make_feature_readonly
|
|
8
8
|
from splent_cli.utils.feature_utils import normalize_namespace
|
|
9
|
-
from splent_cli.utils.proc import
|
|
9
|
+
from splent_cli.utils.proc import require_tool
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
DEFAULT_NAMESPACE = os.getenv("SPLENT_DEFAULT_NAMESPACE", "splent_io")
|
|
@@ -20,8 +20,15 @@ DEFAULT_NAMESPACE = os.getenv("SPLENT_DEFAULT_NAMESPACE", "splent_io")
|
|
|
20
20
|
def _get_latest_tag(namespace, repo) -> str | None:
|
|
21
21
|
"""Fetch the highest semver tag from GitHub. Returns None if unreachable or no tags."""
|
|
22
22
|
api_url = f"https://api.github.com/repos/{namespace}/{repo}/tags?per_page=100"
|
|
23
|
+
# Authenticate when a token is present so version resolution also works for
|
|
24
|
+
# PRIVATE feature repos (an unauthenticated call 404s on those) and to raise
|
|
25
|
+
# the API rate limit.
|
|
26
|
+
headers = {}
|
|
27
|
+
token = os.getenv("GITHUB_TOKEN")
|
|
28
|
+
if token:
|
|
29
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
23
30
|
try:
|
|
24
|
-
r = requests.get(api_url, timeout=5)
|
|
31
|
+
r = requests.get(api_url, headers=headers, timeout=5)
|
|
25
32
|
r.raise_for_status()
|
|
26
33
|
tags = r.json()
|
|
27
34
|
if not tags:
|
|
@@ -42,16 +49,6 @@ def _get_latest_tag(namespace, repo) -> str | None:
|
|
|
42
49
|
return None
|
|
43
50
|
|
|
44
51
|
|
|
45
|
-
def _build_repo_url(namespace, repo):
|
|
46
|
-
"""Build the Git URL, trying SSH first with HTTPS fallback.
|
|
47
|
-
|
|
48
|
-
Returns a tuple (real_url, display_url) where display_url never contains a token.
|
|
49
|
-
"""
|
|
50
|
-
from splent_cli.utils.git_url import build_git_url
|
|
51
|
-
|
|
52
|
-
return build_git_url(namespace, repo)
|
|
53
|
-
|
|
54
|
-
|
|
55
52
|
def _parse_full_name(full_name: str):
|
|
56
53
|
"""
|
|
57
54
|
full_name = <namespace>/<repo>[@version]
|
|
@@ -115,9 +112,6 @@ def feature_clone(full_name):
|
|
|
115
112
|
)
|
|
116
113
|
raise SystemExit(1)
|
|
117
114
|
|
|
118
|
-
# Build Git URL based on your ownership
|
|
119
|
-
fork_url, display_url = _build_repo_url(namespace, repo)
|
|
120
|
-
|
|
121
115
|
# Local destination
|
|
122
116
|
namespace_safe = normalize_namespace(namespace)
|
|
123
117
|
workspace = str(context.workspace())
|
|
@@ -137,98 +131,51 @@ def feature_clone(full_name):
|
|
|
137
131
|
"Install Git from https://git-scm.com/downloads and make sure it is on your PATH.",
|
|
138
132
|
)
|
|
139
133
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
result = run(
|
|
145
|
-
[
|
|
146
|
-
"git",
|
|
147
|
-
"-c",
|
|
148
|
-
"advice.detachedHead=false",
|
|
149
|
-
"clone",
|
|
150
|
-
"--depth",
|
|
151
|
-
"1",
|
|
152
|
-
"--branch",
|
|
153
|
-
version,
|
|
154
|
-
"--quiet",
|
|
155
|
-
fork_url,
|
|
156
|
-
local_path,
|
|
157
|
-
],
|
|
158
|
-
check=False,
|
|
159
|
-
capture=True,
|
|
134
|
+
from splent_cli.utils.git_url import (
|
|
135
|
+
clone as git_clone,
|
|
136
|
+
CLONE_SUCCESS,
|
|
137
|
+
CLONE_REF_NOT_FOUND,
|
|
160
138
|
)
|
|
161
139
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
auth_or_network = any(
|
|
177
|
-
token in stderr_lc
|
|
178
|
-
for token in (
|
|
179
|
-
"authentication failed",
|
|
180
|
-
"permission denied",
|
|
181
|
-
"could not read from remote repository",
|
|
182
|
-
"repository not found",
|
|
183
|
-
"could not resolve host",
|
|
184
|
-
"connection timed out",
|
|
185
|
-
"connection refused",
|
|
186
|
-
"network is unreachable",
|
|
187
|
-
"failed to connect",
|
|
188
|
-
"ssl",
|
|
189
|
-
"tls",
|
|
190
|
-
)
|
|
140
|
+
click.secho(f"⬇️ Cloning {namespace}/{repo}@{version}", fg="cyan")
|
|
141
|
+
|
|
142
|
+
# Always try SSH first, then HTTPS (GITHUB_TOKEN if set, else anonymous). The
|
|
143
|
+
# transport is decided per repo from the real clone result (see
|
|
144
|
+
# git_url.clone), so a working SSH key that simply can't read THIS repo no
|
|
145
|
+
# longer blocks the HTTPS path.
|
|
146
|
+
outcome, used_url, stderr = git_clone(namespace, repo, local_path, ref=version)
|
|
147
|
+
|
|
148
|
+
# A genuinely missing tag/branch is the ONLY case where falling back to the
|
|
149
|
+
# default branch is correct (the repo itself was reachable).
|
|
150
|
+
if outcome == CLONE_REF_NOT_FOUND:
|
|
151
|
+
click.secho(
|
|
152
|
+
f"⚠️ Version '{version}' not found. Cloning default branch instead.",
|
|
153
|
+
fg="yellow",
|
|
191
154
|
)
|
|
155
|
+
outcome, used_url, stderr = git_clone(namespace, repo, local_path, ref=None)
|
|
192
156
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if detail:
|
|
210
|
-
click.secho(detail, fg="red")
|
|
211
|
-
raise SystemExit(1)
|
|
212
|
-
else:
|
|
213
|
-
# Network / auth / unknown git failure: do NOT fall back to main,
|
|
214
|
-
# which would silently install the wrong (unpinned) code.
|
|
215
|
-
click.secho(
|
|
216
|
-
f"❌ Failed to clone '{namespace}/{repo}@{version}'.", fg="red"
|
|
217
|
-
)
|
|
218
|
-
click.secho(
|
|
219
|
-
"This looks like a network, authentication, or repository-access "
|
|
220
|
-
"problem rather than a missing version. Check your connection and "
|
|
221
|
-
"credentials, then try again.",
|
|
222
|
-
fg="red",
|
|
223
|
-
)
|
|
224
|
-
if stderr:
|
|
225
|
-
click.secho(stderr, fg="red")
|
|
226
|
-
raise SystemExit(1)
|
|
157
|
+
if outcome != CLONE_SUCCESS:
|
|
158
|
+
shutil.rmtree(local_path, ignore_errors=True)
|
|
159
|
+
click.secho(
|
|
160
|
+
f"❌ Repository '{namespace}/{repo}' not found or not accessible "
|
|
161
|
+
"(tried SSH and HTTPS).",
|
|
162
|
+
fg="red",
|
|
163
|
+
)
|
|
164
|
+
click.secho(
|
|
165
|
+
"Check your network, that the repo exists, and that you have read "
|
|
166
|
+
"access — an SSH key authorised for the repo, or a GITHUB_TOKEN with "
|
|
167
|
+
"read scope in your .env.",
|
|
168
|
+
fg="red",
|
|
169
|
+
)
|
|
170
|
+
if stderr:
|
|
171
|
+
click.secho(stderr, fg="red")
|
|
172
|
+
raise SystemExit(1)
|
|
227
173
|
|
|
228
174
|
# Lock files as read-only to prevent accidental edits on pinned features
|
|
229
175
|
make_feature_readonly(local_path)
|
|
230
176
|
|
|
231
177
|
click.secho(
|
|
232
|
-
f"✅ Feature '{namespace}/{repo}@{version}' cloned successfully.",
|
|
178
|
+
f"✅ Feature '{namespace}/{repo}@{version}' cloned successfully ({used_url}).",
|
|
179
|
+
fg="green",
|
|
233
180
|
)
|
|
234
181
|
click.secho(f"🔒 Cached (read-only) at: {local_path}", fg="blue")
|
|
@@ -157,9 +157,7 @@ def _compile_in_container(container_id, feature, watch, production, workspace, p
|
|
|
157
157
|
raise click.ClickException(
|
|
158
158
|
f"'{run_cmd[0]}' is not installed or not on PATH.\n{tool_hint}"
|
|
159
159
|
)
|
|
160
|
-
click.echo(
|
|
161
|
-
click.style(f"👀 Watching {feature} in {mode} mode...", fg="blue")
|
|
162
|
-
)
|
|
160
|
+
click.echo(click.style(f"👀 Watching {feature} in {mode} mode...", fg="blue"))
|
|
163
161
|
else:
|
|
164
162
|
result = run(run_cmd, check=False, tool_hint=tool_hint)
|
|
165
163
|
if result.returncode != 0:
|
|
@@ -121,9 +121,7 @@ def feature_env(feature_name, generate, env_name):
|
|
|
121
121
|
try:
|
|
122
122
|
shutil.copy(selected, env_file)
|
|
123
123
|
except OSError as exc:
|
|
124
|
-
click.echo(
|
|
125
|
-
f"❌ Failed to create {env_file} from {selected}: {exc}"
|
|
126
|
-
)
|
|
124
|
+
click.echo(f"❌ Failed to create {env_file} from {selected}: {exc}")
|
|
127
125
|
raise SystemExit(1)
|
|
128
126
|
click.echo(
|
|
129
127
|
f"📄 Created {feature_entry}/docker/.env from {os.path.basename(selected)}"
|
|
@@ -241,7 +241,8 @@ def feature_install(feature_identifier, env_scope, mode, version):
|
|
|
241
241
|
)
|
|
242
242
|
if result.returncode != 0:
|
|
243
243
|
click.secho(
|
|
244
|
-
f" Clone failed: {(result.stderr or '').strip()}",
|
|
244
|
+
f" Clone failed: {(result.stderr or '').strip()}",
|
|
245
|
+
fg="red",
|
|
245
246
|
)
|
|
246
247
|
raise SystemExit(1)
|
|
247
248
|
else:
|
|
@@ -291,9 +292,7 @@ def feature_install(feature_identifier, env_scope, mode, version):
|
|
|
291
292
|
check=False,
|
|
292
293
|
)
|
|
293
294
|
if dep.returncode != 0:
|
|
294
|
-
click.secho(
|
|
295
|
-
f" Installing dependency {m} failed.", fg="red"
|
|
296
|
-
)
|
|
295
|
+
click.secho(f" Installing dependency {m} failed.", fg="red")
|
|
297
296
|
raise SystemExit(1)
|
|
298
297
|
|
|
299
298
|
# Attach to product
|
|
@@ -315,32 +314,27 @@ def feature_install(feature_identifier, env_scope, mode, version):
|
|
|
315
314
|
# Clone to workspace root as editable
|
|
316
315
|
click.echo(click.style(" clone ", dim=True) + f"{short} (editable)")
|
|
317
316
|
from splent_cli.commands.feature.feature_clone import (
|
|
318
|
-
_build_repo_url,
|
|
319
317
|
_get_latest_tag,
|
|
320
318
|
)
|
|
319
|
+
from splent_cli.utils.git_url import (
|
|
320
|
+
clone as git_clone,
|
|
321
|
+
CLONE_SUCCESS,
|
|
322
|
+
CLONE_REF_NOT_FOUND,
|
|
323
|
+
)
|
|
321
324
|
|
|
325
|
+
# SSH first, then HTTPS (per repo). ref=tag (None → default branch).
|
|
322
326
|
tag = _get_latest_tag(namespace_github, feature_name)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
clone = run(
|
|
326
|
-
[
|
|
327
|
-
"git",
|
|
328
|
-
"clone",
|
|
329
|
-
"--depth",
|
|
330
|
-
"1",
|
|
331
|
-
"--branch",
|
|
332
|
-
branch,
|
|
333
|
-
"--quiet",
|
|
334
|
-
repo_url,
|
|
335
|
-
feature_dir,
|
|
336
|
-
],
|
|
337
|
-
check=False,
|
|
338
|
-
capture=True,
|
|
327
|
+
outcome, _used, err = git_clone(
|
|
328
|
+
namespace_github, feature_name, feature_dir, ref=tag
|
|
339
329
|
)
|
|
340
|
-
if
|
|
330
|
+
if outcome == CLONE_REF_NOT_FOUND:
|
|
331
|
+
outcome, _used, err = git_clone(
|
|
332
|
+
namespace_github, feature_name, feature_dir, ref=None
|
|
333
|
+
)
|
|
334
|
+
if outcome != CLONE_SUCCESS:
|
|
341
335
|
click.secho(
|
|
342
|
-
f" Could not clone {namespace_github}/{feature_name}
|
|
343
|
-
f"
|
|
336
|
+
f" Could not clone {namespace_github}/{feature_name} "
|
|
337
|
+
f"(tried SSH and HTTPS): {err}",
|
|
344
338
|
fg="red",
|
|
345
339
|
)
|
|
346
340
|
raise SystemExit(1)
|
|
@@ -386,9 +380,7 @@ def feature_install(feature_identifier, env_scope, mode, version):
|
|
|
386
380
|
check=False,
|
|
387
381
|
)
|
|
388
382
|
if dep.returncode != 0:
|
|
389
|
-
click.secho(
|
|
390
|
-
f" Installing dependency {m} failed.", fg="red"
|
|
391
|
-
)
|
|
383
|
+
click.secho(f" Installing dependency {m} failed.", fg="red")
|
|
392
384
|
raise SystemExit(1)
|
|
393
385
|
|
|
394
386
|
# Add to product
|
|
@@ -454,7 +446,8 @@ def feature_install(feature_identifier, env_scope, mode, version):
|
|
|
454
446
|
)
|
|
455
447
|
if result.returncode != 0:
|
|
456
448
|
click.secho(
|
|
457
|
-
f" Docker failed: {(result.stderr or '').strip()}",
|
|
449
|
+
f" Docker failed: {(result.stderr or '').strip()}",
|
|
450
|
+
fg="yellow",
|
|
458
451
|
)
|
|
459
452
|
|
|
460
453
|
click.echo()
|
|
@@ -364,9 +364,7 @@ def _scaffold_service(
|
|
|
364
364
|
repos_path = os.path.join(
|
|
365
365
|
feature_path, "src", ns_safe, feature_name, "repositories.py"
|
|
366
366
|
)
|
|
367
|
-
if os.path.isfile(repos_path) and _confirm_overwrite(
|
|
368
|
-
repos_path, "repositories.py"
|
|
369
|
-
):
|
|
367
|
+
if os.path.isfile(repos_path) and _confirm_overwrite(repos_path, "repositories.py"):
|
|
370
368
|
with open(repos_path, "w") as f:
|
|
371
369
|
f.write(
|
|
372
370
|
"# Refinement features do not need their own repository.\n"
|
|
@@ -875,8 +873,7 @@ def feature_refinement(refiner_name):
|
|
|
875
873
|
tomllib.loads(content)
|
|
876
874
|
except tomllib.TOMLDecodeError as e:
|
|
877
875
|
click.secho(
|
|
878
|
-
f" Refusing to write pyproject.toml: the result is not valid TOML.\n"
|
|
879
|
-
f" {e}",
|
|
876
|
+
f" Refusing to write pyproject.toml: the result is not valid TOML.\n {e}",
|
|
880
877
|
fg="red",
|
|
881
878
|
)
|
|
882
879
|
raise SystemExit(1)
|
|
@@ -555,8 +555,13 @@ def create_versioned_snapshot(namespace, feature_name, version, workspace):
|
|
|
555
555
|
@click.argument("feature_ref")
|
|
556
556
|
@click.argument("version", required=False, default=None)
|
|
557
557
|
@click.option("--attach", is_flag=True)
|
|
558
|
+
@click.option(
|
|
559
|
+
"--skip-checks",
|
|
560
|
+
is_flag=True,
|
|
561
|
+
help="Skip the pre-release lint + tests gate (emergencies only).",
|
|
562
|
+
)
|
|
558
563
|
@context.requires_product
|
|
559
|
-
def feature_release(feature_ref, version, attach):
|
|
564
|
+
def feature_release(feature_ref, version, attach, skip_checks):
|
|
560
565
|
workspace = str(context.workspace())
|
|
561
566
|
|
|
562
567
|
feature_path, namespace, feature_name = resolve_feature_path(feature_ref, workspace)
|
|
@@ -583,6 +588,8 @@ def feature_release(feature_ref, version, attach):
|
|
|
583
588
|
f"{namespace}/{feature_name}",
|
|
584
589
|
feature_path,
|
|
585
590
|
version,
|
|
591
|
+
kind="feature",
|
|
592
|
+
skip_checks=skip_checks,
|
|
586
593
|
pre_commit_hook=_pre_commit,
|
|
587
594
|
post_pypi_hook=_post_pypi,
|
|
588
595
|
)
|
|
@@ -23,18 +23,14 @@ def _github_request(url: str, token: str | None) -> dict | list | None:
|
|
|
23
23
|
if e.code in (403, 429):
|
|
24
24
|
remaining = e.headers.get("X-RateLimit-Remaining") if e.headers else None
|
|
25
25
|
if e.code == 429 or remaining == "0":
|
|
26
|
-
click.secho(
|
|
27
|
-
"❌ GitHub API rate limit exceeded.", fg="red"
|
|
28
|
-
)
|
|
26
|
+
click.secho("❌ GitHub API rate limit exceeded.", fg="red")
|
|
29
27
|
if not token:
|
|
30
28
|
click.secho(
|
|
31
29
|
"💡 Set GITHUB_TOKEN to raise your rate limit and access private repos.",
|
|
32
30
|
fg="yellow",
|
|
33
31
|
)
|
|
34
32
|
raise SystemExit(1)
|
|
35
|
-
click.secho(
|
|
36
|
-
f"❌ GitHub API access forbidden (HTTP {e.code}).", fg="red"
|
|
37
|
-
)
|
|
33
|
+
click.secho(f"❌ GitHub API access forbidden (HTTP {e.code}).", fg="red")
|
|
38
34
|
if not token:
|
|
39
35
|
click.secho(
|
|
40
36
|
"💡 Set GITHUB_TOKEN to access private repos and raise rate limits.",
|
|
@@ -9,8 +9,10 @@ import click
|
|
|
9
9
|
from packaging.version import Version, InvalidVersion
|
|
10
10
|
|
|
11
11
|
from splent_cli.services import context
|
|
12
|
-
from splent_cli.utils.feature_utils import
|
|
13
|
-
|
|
12
|
+
from splent_cli.utils.feature_utils import (
|
|
13
|
+
normalize_namespace,
|
|
14
|
+
read_features_from_data,
|
|
15
|
+
)
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
# ── GitHub helpers ────────────────────────────────────────────────────────────
|
|
@@ -82,13 +84,22 @@ def _read_features(pyproject_path: Path) -> list[dict]:
|
|
|
82
84
|
else:
|
|
83
85
|
name, version = rest, None
|
|
84
86
|
result.append(
|
|
85
|
-
{
|
|
87
|
+
{
|
|
88
|
+
"name": name,
|
|
89
|
+
"version": version,
|
|
90
|
+
"ns_github": ns_github,
|
|
91
|
+
"ns_fs": ns_fs,
|
|
92
|
+
}
|
|
86
93
|
)
|
|
87
94
|
return result
|
|
88
95
|
|
|
89
96
|
|
|
90
97
|
def _update_pyproject(
|
|
91
|
-
pyproject_path: Path,
|
|
98
|
+
pyproject_path: Path,
|
|
99
|
+
ns_github: str,
|
|
100
|
+
name: str,
|
|
101
|
+
old_ver: str | None,
|
|
102
|
+
new_ver: str,
|
|
92
103
|
):
|
|
93
104
|
content = pyproject_path.read_text()
|
|
94
105
|
if old_ver:
|
|
@@ -109,16 +120,16 @@ def _clone_if_missing(ns_fs: str, name: str, version: str, cache_root: Path):
|
|
|
109
120
|
if target.exists():
|
|
110
121
|
return
|
|
111
122
|
ns_github = ns_fs.replace("_", "-")
|
|
112
|
-
from splent_cli.utils.git_url import
|
|
123
|
+
from splent_cli.utils.git_url import clone as git_clone, CLONE_SUCCESS
|
|
113
124
|
|
|
114
|
-
url, _ = build_git_url(ns_github, name)
|
|
115
125
|
click.echo(f" ⬇️ Cloning {ns_fs}/{name}@{version}...")
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
# SSH first, then HTTPS. A pinned version that doesn't exist stays an error
|
|
127
|
+
# here — upgrade must not silently fall back to a different ref.
|
|
128
|
+
outcome, _used, err = git_clone(ns_github, name, str(target), ref=version)
|
|
129
|
+
if outcome != CLONE_SUCCESS:
|
|
130
|
+
raise click.ClickException(
|
|
131
|
+
f"Could not clone {ns_fs}/{name}@{version} (tried SSH and HTTPS). {err}".strip()
|
|
132
|
+
)
|
|
122
133
|
from splent_cli.utils.cache_utils import make_feature_readonly
|
|
123
134
|
|
|
124
135
|
make_feature_readonly(str(target))
|
|
@@ -242,7 +253,11 @@ def feature_upgrade(feature_ref, yes):
|
|
|
242
253
|
try:
|
|
243
254
|
_clone_if_missing(u["ns_fs"], u["name"], u["latest"], cache_root)
|
|
244
255
|
_update_pyproject(
|
|
245
|
-
pyproject_path,
|
|
256
|
+
pyproject_path,
|
|
257
|
+
u["ns_github"],
|
|
258
|
+
u["name"],
|
|
259
|
+
u["version"],
|
|
260
|
+
u["latest"],
|
|
246
261
|
)
|
|
247
262
|
_update_symlink(
|
|
248
263
|
product_path,
|
|
@@ -258,7 +273,8 @@ def feature_upgrade(feature_ref, yes):
|
|
|
258
273
|
|
|
259
274
|
click.echo()
|
|
260
275
|
click.secho(
|
|
261
|
-
" Done. Run 'splent product:resolve' to reinstall pip dependencies.",
|
|
276
|
+
" Done. Run 'splent product:resolve' to reinstall pip dependencies.",
|
|
277
|
+
fg="cyan",
|
|
262
278
|
)
|
|
263
279
|
click.echo()
|
|
264
280
|
|
|
@@ -72,7 +72,9 @@ def linter(fix, targets):
|
|
|
72
72
|
label = f"{'Fixing' if fix else 'Checking'} {directory}"
|
|
73
73
|
click.echo(click.style(f"🔍 {label}...\n", fg="yellow"))
|
|
74
74
|
|
|
75
|
-
result = run(
|
|
75
|
+
result = run(
|
|
76
|
+
lint_cmd + [directory], check=False, capture=True, tool_hint=_RUFF_HINT
|
|
77
|
+
)
|
|
76
78
|
|
|
77
79
|
output = (result.stdout + result.stderr).strip()
|
|
78
80
|
if result.returncode != 0:
|
|
@@ -179,9 +179,7 @@ def locust(module):
|
|
|
179
179
|
try:
|
|
180
180
|
client = docker.from_env()
|
|
181
181
|
except docker.errors.DockerException as e:
|
|
182
|
-
raise click.ClickException(
|
|
183
|
-
f"Could not connect to the Docker daemon: {e}"
|
|
184
|
-
)
|
|
182
|
+
raise click.ClickException(f"Could not connect to the Docker daemon: {e}")
|
|
185
183
|
|
|
186
184
|
try:
|
|
187
185
|
web_container = client.containers.get("web_app_container")
|
|
@@ -247,9 +245,7 @@ def stop():
|
|
|
247
245
|
try:
|
|
248
246
|
os.kill(proc.pid, signal.SIGTERM)
|
|
249
247
|
except (ProcessLookupError, PermissionError) as e:
|
|
250
|
-
click.secho(
|
|
251
|
-
f"⚠️ Could not stop PID {proc.pid}: {e}", fg="yellow"
|
|
252
|
-
)
|
|
248
|
+
click.secho(f"⚠️ Could not stop PID {proc.pid}: {e}", fg="yellow")
|
|
253
249
|
|
|
254
250
|
def stop_docker_locust():
|
|
255
251
|
click.echo("Stopping Locust container if it is running...")
|
|
@@ -55,7 +55,9 @@ def product_clean(env_dev, env_prod, yes):
|
|
|
55
55
|
product = context.require_app()
|
|
56
56
|
|
|
57
57
|
click.secho(f"\n⚠️ This will completely wipe {product} ({env}):", fg="yellow")
|
|
58
|
-
click.echo(
|
|
58
|
+
click.echo(
|
|
59
|
+
" - Stop all Docker containers and DELETE ALL VOLUMES/DATA (irreversible)"
|
|
60
|
+
)
|
|
59
61
|
click.echo(" - Reset the database and regenerate migrations")
|
|
60
62
|
click.echo(" - Clear uploads and application log")
|
|
61
63
|
click.echo()
|
|
@@ -263,13 +263,7 @@ def make_product(name, spl_name, features_file, force):
|
|
|
263
263
|
gid = 1000
|
|
264
264
|
do_chown = sys.platform.startswith("linux")
|
|
265
265
|
dir_mode = stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH
|
|
266
|
-
file_mode =
|
|
267
|
-
stat.S_IRUSR
|
|
268
|
-
| stat.S_IWUSR
|
|
269
|
-
| stat.S_IRGRP
|
|
270
|
-
| stat.S_IWGRP
|
|
271
|
-
| stat.S_IROTH
|
|
272
|
-
)
|
|
266
|
+
file_mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH
|
|
273
267
|
|
|
274
268
|
def _maybe_chown(path):
|
|
275
269
|
if not do_chown:
|
|
@@ -29,7 +29,7 @@ def _parse_env_line(line: str):
|
|
|
29
29
|
return None
|
|
30
30
|
|
|
31
31
|
if stripped.startswith("export ") or stripped.startswith("export\t"):
|
|
32
|
-
stripped = stripped[len("export"):].lstrip()
|
|
32
|
+
stripped = stripped[len("export") :].lstrip()
|
|
33
33
|
|
|
34
34
|
key, value = stripped.split("=", 1)
|
|
35
35
|
key = key.strip()
|