weightslab 1.2.6__tar.gz → 1.3.1__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.
- {weightslab-1.2.6 → weightslab-1.3.1}/.github/workflows/ci.yml +10 -29
- {weightslab-1.2.6 → weightslab-1.3.1}/.github/workflows/release.yml +297 -49
- {weightslab-1.2.6 → weightslab-1.3.1}/AGENTS.md +12 -5
- weightslab-1.3.1/CHANGELOG.md +1 -0
- weightslab-1.3.1/PKG-INFO +390 -0
- weightslab-1.3.1/README.md +331 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/agent_config.yaml +7 -1
- weightslab-1.3.1/docs/_static/custom.css +584 -0
- weightslab-1.3.1/docs/_static/examples-gallery.js +208 -0
- weightslab-1.3.1/docs/_static/github-stars.js +17 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_static/version-switcher.js +10 -11
- weightslab-1.3.1/docs/_static/wl-ribbon.js +49 -0
- weightslab-1.3.1/docs/_static/wl-topnav.js +89 -0
- weightslab-1.3.1/docs/_templates/sidebar/brand.html +21 -0
- weightslab-1.3.1/docs/agent.rst +650 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/conf.py +15 -5
- weightslab-1.3.1/docs/configuration.rst +1082 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/data_exploration.rst +6 -0
- weightslab-1.3.1/docs/examples/index.rst +21 -0
- weightslab-1.3.1/docs/examples/lightning/classification.rst +119 -0
- weightslab-1.3.1/docs/examples/lightning/index.rst +19 -0
- weightslab-1.3.1/docs/examples/pytorch/classification.rst +161 -0
- weightslab-1.3.1/docs/examples/pytorch/clustering.rst +97 -0
- weightslab-1.3.1/docs/examples/pytorch/detection.rst +129 -0
- weightslab-1.3.1/docs/examples/pytorch/generation.rst +103 -0
- weightslab-1.3.1/docs/examples/pytorch/index.rst +23 -0
- weightslab-1.3.1/docs/examples/pytorch/segmentation.rst +116 -0
- weightslab-1.3.1/docs/examples/ultralytics/detection.rst +47 -0
- weightslab-1.3.1/docs/examples/ultralytics/index.rst +19 -0
- weightslab-1.3.1/docs/examples/usecases/index.rst +20 -0
- weightslab-1.3.1/docs/examples/usecases/lidar_detection.rst +126 -0
- weightslab-1.3.1/docs/examples/usecases/loss_shape_classification.rst +210 -0
- weightslab-1.3.1/docs/four_way_approach.rst +58 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/grpc/audit_logger.rst +4 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/grpc/grpc_functions.rst +0 -1
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/index.rst +71 -16
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/logger.rst +31 -0
- weightslab-1.3.1/docs/quickstart.rst +193 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/segmentation_usecase.rst +1 -1
- weightslab-1.3.1/docs/ultralytics.rst +224 -0
- weightslab-1.3.1/docs/usage/docker.rst +350 -0
- weightslab-1.3.1/docs/usage/good_practice.rst +211 -0
- weightslab-1.3.1/docs/usage/parameters.rst +528 -0
- weightslab-1.3.1/docs/usage.rst +18 -0
- weightslab-1.3.1/docs/user_commands.rst +440 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/user_functions.rst +437 -15
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/weights_studio.rst +26 -42
- {weightslab-1.2.6 → weightslab-1.3.1}/pyproject.toml +26 -4
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/__init__.py +1 -1
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_compare_dataloaders.py +65 -65
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_data_loader_interface.py +65 -65
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_instance_signal_logger.py +28 -37
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_ledgers.py +57 -3
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_logger_core.py +162 -54
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_ui_docker_bridge.py +15 -15
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_write_dataframe.py +3 -3
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_write_history.py +5 -5
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/chaos_monkeys_utests/test_grpc_chaos_monkey_robustness.py +1 -1
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/components/test_checkpoint_workflow.py +68 -64
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/components/test_global_monitoring_unit.py +21 -21
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/gRPC/test_get_point_cloud.py +39 -1
- weightslab-1.3.1/tests/gRPC/test_grpc_histogram_categorical.py +205 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/gRPC/test_grpc_tag_operations.py +26 -26
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/gRPC/test_grpc_user_actions.py +53 -11
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/general/test_cli.py +181 -87
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/general/test_signals.py +10 -10
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/general/test_signals_wrapping.py +4 -4
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/integrations/test_pytorch_lightning_integration.py +112 -112
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/integrations/ultralytics/ddp/ddp_ablation.py +13 -13
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/integrations/ultralytics/ddp/ddp_test_suite.py +108 -108
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/model/test_constraint_generation.py +4 -4
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/model/test_dependency_patterns.py +6 -6
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/model/test_model_with_ops.py +2 -2
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/model/test_tracking.py +1 -1
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/modules/test_modules_with_ops.py +18 -18
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/test_secure_docker.py +1 -1
- weightslab-1.3.1/tests/trainer/services/test_agent_live_prompt_evaluation.py +1120 -0
- weightslab-1.3.1/tests/trainer/services/test_agent_model_and_safety_unit.py +1677 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/trainer/services/test_agent_prompt_unit.py +30 -2
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/trainer/services/test_agent_service_unit.py +2 -2
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/trainer/services/test_trainer_services_server.py +1 -1
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/trainer/services/test_trainer_services_unit.py +118 -16
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/watchdog/test_lock_monitor.py +1 -1
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/watchdog/test_watchdog.py +14 -14
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/__init__.py +71 -8
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/_version.py +3 -3
- weightslab-1.3.1/weightslab/art.py +164 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/backend/audit_logger.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/backend/cli.py +132 -8
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/backend/dataloader_interface.py +39 -39
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/backend/ledgers.py +113 -19
- weightslab-1.3.1/weightslab/backend/logger.py +1168 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/backend/model_interface.py +25 -16
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/backend/optimizer_interface.py +1 -1
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/__init__.py +9 -9
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/checkpoint_manager.py +102 -102
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/experiment_hash.py +9 -9
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/global_monitoring.py +17 -10
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/parallel_primitives.py +15 -15
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/tracking.py +10 -10
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/array_proxy.py +3 -3
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/data_samples_with_ops.py +20 -20
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/data_utils.py +40 -33
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/dataframe_manager.py +48 -44
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/h5_array_store.py +7 -7
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/h5_dataframe_store.py +44 -25
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/point_cloud_utils.py +21 -21
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/data/sample_stats.py +6 -6
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/docker-compose.yml +16 -1
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/nginx-entrypoint.sh +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/test-deployment.sh +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/utils/build-and-deploy.sh +57 -6
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/utils/generate-certs-auth-token.ps1 +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/utils/generate-certs-auth-token.sh +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/utils/test-deployment.sh +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/docker_in_docker/Dockerfile +1 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/siblings_self_contained/Dockerfile +1 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Lightning/ws-classification/main.py +11 -11
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-classification/config.yaml +4 -4
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-classification/main.py +28 -21
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-clustering/face/data.py +47 -47
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-clustering/face/model.py +22 -22
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-clustering/face/signals.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-clustering/face/utils.py +7 -7
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-clustering/main.py +23 -23
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-detection/main.py +16 -16
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-detection/utils/criterions.py +18 -18
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-detection/utils/data.py +15 -15
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-detection/utils/model.py +11 -11
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-generation/main.py +23 -23
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/config.yaml +2 -1
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/main.py +51 -31
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/utils/criterions.py +9 -9
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/utils/data.py +19 -8
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/utils/model.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Ultralytics/ws-detection/config.yaml +3 -3
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Ultralytics/ws-detection/main.py +13 -9
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-2d-lidar-detection/config.yaml +1 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-2d-lidar-detection/main.py +6 -6
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/criterions.py +4 -4
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/data.py +8 -8
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/model.py +12 -12
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/main.py +34 -34
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/criterions.py +25 -25
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/data.py +47 -47
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/kitti_download.py +5 -5
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/model.py +28 -28
- weightslab-1.3.1/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/README.md +102 -0
- weightslab-1.3.1/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/config.yaml +50 -0
- weightslab-1.3.1/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/main.py +340 -0
- weightslab-1.3.1/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/criterions.py +361 -0
- weightslab-1.3.1/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/data.py +226 -0
- weightslab-1.3.1/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/model.py +134 -0
- weightslab-1.3.1/weightslab/examples/__init__.py +6 -0
- weightslab-1.3.1/weightslab/examples/utils/__init__.py +1 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1/weightslab/examples/utils}/baseline_models/pytorch/models.py +65 -65
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/__init__.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/dataset.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/signals.py +12 -12
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/trainer.py +10 -10
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/models/model_with_ops.py +4 -4
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/models/monkey_patcher.py +1 -1
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/modules/modules_with_ops.py +27 -27
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/proto/experiment_service.proto +71 -0
- weightslab-1.3.1/weightslab/proto/experiment_service_pb2.py +196 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/proto/experiment_service_pb2_grpc.py +91 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/security/cert_auth_manager.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/src.py +173 -158
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/experiment_context.py +8 -4
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/agent/agent.py +836 -39
- weightslab-1.3.1/weightslab/trainer/services/agent/intent_prompt.py +843 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/agent_service.py +5 -5
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/data_image_utils.py +3 -3
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/data_service.py +1300 -261
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/experiment_service.py +249 -14
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/instance_merger.py +6 -6
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/model_service.py +12 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/utils/tools.py +1 -1
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/trainer_services.py +19 -12
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/trainer_tools.py +21 -19
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/ui_docker_bridge.py +171 -69
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/computational_graph.py +92 -92
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/logs.py +1 -1
- weightslab-1.3.1/weightslab/utils/telemetry.py +152 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/tools.py +18 -16
- weightslab-1.3.1/weightslab/watchdog/__init__.py +30 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/watchdog/grpc_watchdog.py +2 -2
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/watchdog/lock_monitor.py +7 -7
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/watchdog/log_level.py +1 -1
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/watchdog/watchdog.py +20 -20
- weightslab-1.3.1/weightslab.egg-info/PKG-INFO +390 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab.egg-info/SOURCES.txt +127 -97
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab.egg-info/requires.txt +2 -2
- weightslab-1.3.1/weightslab.egg-info/scm_file_list.json +342 -0
- weightslab-1.3.1/weightslab.egg-info/scm_version.json +8 -0
- weightslab-1.2.6/CHANGELOG.md +0 -1
- weightslab-1.2.6/PKG-INFO +0 -481
- weightslab-1.2.6/README.md +0 -422
- weightslab-1.2.6/docs/_static/custom.css +0 -143
- weightslab-1.2.6/docs/configuration.rst +0 -549
- weightslab-1.2.6/docs/four_way_approach.rst +0 -29
- weightslab-1.2.6/docs/quickstart.rst +0 -191
- weightslab-1.2.6/weightslab/art.py +0 -58
- weightslab-1.2.6/weightslab/backend/logger.py +0 -1058
- weightslab-1.2.6/weightslab/examples/Ultralytics/ws-detection/requirements.txt +0 -1
- weightslab-1.2.6/weightslab/proto/experiment_service_pb2.py +0 -180
- weightslab-1.2.6/weightslab/tests/data/test_data_samples_with_ops.py +0 -783
- weightslab-1.2.6/weightslab/tests/data/test_data_service_metadata_copy.py +0 -97
- weightslab-1.2.6/weightslab/tests/data/test_data_utils_unit.py +0 -117
- weightslab-1.2.6/weightslab/tests/data/test_dataframe_manager_unit.py +0 -428
- weightslab-1.2.6/weightslab/tests/data/test_flush_pipeline.py +0 -277
- weightslab-1.2.6/weightslab/tests/data/test_h5_array_store.py +0 -217
- weightslab-1.2.6/weightslab/tests/data/test_h5_dataframe_store.py +0 -219
- weightslab-1.2.6/weightslab/tests/data/test_point_cloud_utils.py +0 -330
- weightslab-1.2.6/weightslab/trainer/services/agent/intent_prompt.py +0 -426
- weightslab-1.2.6/weightslab/trainer/services/utils/__init__.py +0 -0
- weightslab-1.2.6/weightslab/watchdog/__init__.py +0 -30
- weightslab-1.2.6/weightslab.egg-info/PKG-INFO +0 -481
- {weightslab-1.2.6 → weightslab-1.3.1}/.gitattributes +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/.github/workflows/docs-pages.yml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/.gitignore +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/LICENSE +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_static/.gitkeep +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_static/favicon.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_static/logo-dark.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_static/logo-light.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_static/weights_studio_architecture.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/_templates/.gitkeep +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/grpc/index.rst +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/hyperparameters.rst +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/model_interaction.rst +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/pytorch_lightning.rst +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/requirements.txt +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/docs/usecases.rst +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/setup.cfg +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1/tests}/backend/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_audit_logger.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_cli_additional_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_model_interface_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_optimizer_interface.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/backend/test_optimizer_interface_additional_unit.py +0 -0
- {weightslab-1.2.6/weightslab/baseline_models → weightslab-1.3.1/tests/chaos_monkeys_utests}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/baseline_models/pytorch → weightslab-1.3.1/tests/components}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/components/test_experiment_hash_and_art.py +0 -0
- {weightslab-1.2.6/weightslab/data → weightslab-1.3.1/tests/gRPC}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/examples/PyTorch/ws-clustering/face → weightslab-1.3.1/tests/general}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/general/test_auditor_mode.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/general/test_hyperparams.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/general/test_logger_snapshot_rotation.py +0 -0
- {weightslab-1.2.6/weightslab/models → weightslab-1.3.1/tests/integrations}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/modules → weightslab-1.3.1/tests/model}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/model/test_logger.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/model/test_model_with_ops_unit.py +0 -0
- {weightslab-1.2.6/weightslab/proto → weightslab-1.3.1/tests/modules}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/test_src_functions.py +0 -0
- {weightslab-1.2.6/weightslab/tests/backend → weightslab-1.3.1/tests/trainer}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/tests/chaos_monkeys_utests → weightslab-1.3.1/tests/trainer/services}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/trainer/test_trainer_tools.py +0 -0
- {weightslab-1.2.6/weightslab/tests/components → weightslab-1.3.1/tests/utils}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_computational_graph_utils_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_logs_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_modules_dependencies_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_plot_graph_render_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_plot_graph_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_shape_prop_unit.py +0 -0
- {weightslab-1.2.6/weightslab → weightslab-1.3.1}/tests/utils/test_utils_tools_unit.py +0 -0
- {weightslab-1.2.6/weightslab/tests/data → weightslab-1.3.1/tests/watchdog}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/tests/gRPC → weightslab-1.3.1/weightslab/backend}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/components/evaluation_controller.py +0 -0
- {weightslab-1.2.6/weightslab/tests/general → weightslab-1.3.1/weightslab/data}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/Dockerfile +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/.dockerignore +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/.env.example +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/DEPLOYMENT.md +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/nginx.base-path.conf copy.template +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/nginx.base-path.conf.template +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/docker/nginx.conf +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/envoy/envoy.downstream_plaintext.yaml +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/envoy/envoy.downstream_upstream_plaintext.yaml +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/envoy/envoy.upstream_plaintext.yaml +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/envoy/envoy.yaml +0 -0
- {weightslab-1.2.6/weightslab/ui → weightslab-1.3.1/weightslab/docker}/nginx.conf +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/docker_in_docker/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/docker_in_docker/docker-compose.yml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/docker_in_docker/entrypoint.sh +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/siblings_self_contained/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/siblings_self_contained/docker-compose.yml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/siblings_self_contained/entrypoint.sh +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Docker_training/siblings_self_contained/ui-compose.yml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Lightning/ws-classification/config.yaml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-clustering/config.yaml +0 -0
- {weightslab-1.2.6/weightslab/tests/integrations → weightslab-1.3.1/weightslab/examples/PyTorch/ws-clustering/face}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-detection/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-detection/config.yaml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-generation/config.yaml +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0000f77c-6257be58.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/000f8d37-d4c09a0f.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00a0f008-a315437f.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c12bd0-bb46e479.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c29c52-f9524f1e.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00ce6f6d-50bbee62.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d1bafa-1b47b41c.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d7268f-fd4487be.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00f0dd0f-5e9c9557.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a0d7f4c-ac5c3c8f.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a1f4fce-f9cac880.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a3bb2d8-c195d91e.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1cac6a7-04e33135.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ceb32e-3f481b43.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d10d08-5b108225.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d22449-15fb948f.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d7b3ac-5af8623b.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1dce572-c6a8cb5e.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e1a7b8-0aec80e8.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e8ad72-c3c79240.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ee702d-0ae1fc10.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1f0efd9-37a14dda.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2a0648b-d8e126bc.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2b70230-bad4ff6e.jpg +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0000f77c-6257be58.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/000f8d37-d4c09a0f.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00a0f008-a315437f.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c12bd0-bb46e479.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c29c52-f9524f1e.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00ce6f6d-50bbee62.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d1bafa-1b47b41c.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d7268f-fd4487be.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00f0dd0f-5e9c9557.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a0d7f4c-ac5c3c8f.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a1f4fce-f9cac880.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a3bb2d8-c195d91e.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1cac6a7-04e33135.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ceb32e-3f481b43.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d10d08-5b108225.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d22449-15fb948f.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d7b3ac-5af8623b.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1dce572-c6a8cb5e.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e1a7b8-0aec80e8.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e8ad72-c3c79240.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ee702d-0ae1fc10.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1f0efd9-37a14dda.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2a0648b-d8e126bc.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2b70230-bad4ff6e.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-2d-lidar-detection/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/examples/Usecases/ws-3d-lidar-detection/config.yaml +0 -0
- {weightslab-1.2.6/weightslab/tests/model → weightslab-1.3.1/weightslab/examples/utils/baseline_models}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/tests/modules → weightslab-1.3.1/weightslab/examples/utils/baseline_models/pytorch}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/README.md +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/_utils.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/integrations/ultralytics/collate.py +0 -0
- {weightslab-1.2.6/weightslab/tests/trainer → weightslab-1.3.1/weightslab/models}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/tests/trainer/services → weightslab-1.3.1/weightslab/modules}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/modules/neuron_ops.py +0 -0
- {weightslab-1.2.6/weightslab/tests/utils → weightslab-1.3.1/weightslab/proto}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/security/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/tests/watchdog → weightslab-1.3.1/weightslab/trainer}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/trainer → weightslab-1.3.1/weightslab/trainer/services}/__init__.py +0 -0
- {weightslab-1.2.6/weightslab/trainer/services → weightslab-1.3.1/weightslab/trainer/services/agent}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/agent/agent_overview/agent.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/agent/agent_overview/query_example.png +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/trainer/services/agent/agent_overview/schema.png +0 -0
- {weightslab-1.2.6/weightslab/trainer/services/agent → weightslab-1.3.1/weightslab/trainer/services/utils}/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/__init__.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/modules_dependencies.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/plot_graph.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab/utils/shape_prop.py +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab.egg-info/dependency_links.txt +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab.egg-info/entry_points.txt +0 -0
- {weightslab-1.2.6 → weightslab-1.3.1}/weightslab.egg-info/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ on:
|
|
|
9
9
|
branches: [ '**' ]
|
|
10
10
|
tags: [ 'v*' ]
|
|
11
11
|
pull_request:
|
|
12
|
-
types: [ opened, reopened, ready_for_review ]
|
|
12
|
+
types: [ opened, reopened, ready_for_review, synchronize ]
|
|
13
13
|
workflow_dispatch:
|
|
14
14
|
|
|
15
15
|
jobs:
|
|
@@ -32,8 +32,8 @@ jobs:
|
|
|
32
32
|
run_ci=true # PRs and manual dispatch always run
|
|
33
33
|
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
|
34
34
|
run_ci=false # tag pushes are handled by the release workflow
|
|
35
|
-
elif [ "${{ github.ref }}" = "refs/heads/main" ] || [ "${{ github.ref }}" = "refs/heads/dev" ]; then
|
|
36
|
-
run_ci=true # default branches always run
|
|
35
|
+
elif [ "${{ github.ref }}" = "refs/heads/main" ] || [ "${{ github.ref }}" = "refs/heads/dev" ] || [[ "${{ github.ref }}" == refs/heads/v* ]]; then
|
|
36
|
+
run_ci=true # default branches and release branches (v*) always run
|
|
37
37
|
elif [ "${FORCE_CI}" = "true" ]; then
|
|
38
38
|
run_ci=true # custom branch opted in via [force ci]
|
|
39
39
|
else
|
|
@@ -57,7 +57,7 @@ jobs:
|
|
|
57
57
|
|
|
58
58
|
- name: Set up Python
|
|
59
59
|
id: setup-python
|
|
60
|
-
uses: actions/setup-python@
|
|
60
|
+
uses: actions/setup-python@v6
|
|
61
61
|
with:
|
|
62
62
|
python-version: '3.11'
|
|
63
63
|
|
|
@@ -141,7 +141,7 @@ jobs:
|
|
|
141
141
|
uses: actions/checkout@v4
|
|
142
142
|
|
|
143
143
|
- name: Set up Python 3.11
|
|
144
|
-
uses: actions/setup-python@
|
|
144
|
+
uses: actions/setup-python@v6
|
|
145
145
|
with:
|
|
146
146
|
python-version: '3.11'
|
|
147
147
|
|
|
@@ -179,7 +179,7 @@ jobs:
|
|
|
179
179
|
uses: actions/checkout@v4
|
|
180
180
|
|
|
181
181
|
- name: Set up Python ${{ matrix.python-version }}
|
|
182
|
-
uses: actions/setup-python@
|
|
182
|
+
uses: actions/setup-python@v6
|
|
183
183
|
with:
|
|
184
184
|
python-version: ${{ matrix.python-version }}
|
|
185
185
|
allow-prereleases: ${{ matrix.allow-prereleases || false }}
|
|
@@ -204,7 +204,7 @@ jobs:
|
|
|
204
204
|
uses: actions/checkout@v4
|
|
205
205
|
|
|
206
206
|
- name: Set up Python
|
|
207
|
-
uses: actions/setup-python@
|
|
207
|
+
uses: actions/setup-python@v6
|
|
208
208
|
with:
|
|
209
209
|
python-version: '3.11'
|
|
210
210
|
|
|
@@ -221,26 +221,7 @@ jobs:
|
|
|
221
221
|
run: |
|
|
222
222
|
export WEIGHTSLAB_LOG_LEVEL="DEBUG"
|
|
223
223
|
# A per-test timeout guards against any regression that hangs a test.
|
|
224
|
-
python -m pytest ./
|
|
225
|
-
|
|
226
|
-
# TODO (GP): WL CI do not find WS CI for now; token or visibility problem ??
|
|
227
|
-
# - name: Trigger WeightsStudio CI
|
|
228
|
-
# env:
|
|
229
|
-
# WS_TOKEN: ${{ secrets.WEIGHTS_STUDIO_API_TOKEN }}
|
|
230
|
-
# run: |
|
|
231
|
-
# if [ -z "${WS_TOKEN}" ]; then
|
|
232
|
-
# echo "WEIGHTS_STUDIO_API_TOKEN not set; skipping WeightsStudio trigger."
|
|
233
|
-
# exit 0
|
|
234
|
-
# fi
|
|
235
|
-
|
|
236
|
-
# # Trigger the ws-ci workflow in the weights_studio repository on main.
|
|
237
|
-
# curl -fSs -X POST "https://api.github.com/repos/GrayboxTech/weights_studio/actions/workflows/ws-ci.yml/dispatches" \
|
|
238
|
-
# -H "Authorization: Bearer ${WS_TOKEN}" \
|
|
239
|
-
# -H "Accept: application/vnd.github+json" \
|
|
240
|
-
# -H "Content-Type: application/json" \
|
|
241
|
-
# -d '{"ref":"main"}'
|
|
242
|
-
|
|
243
|
-
# echo "WeightsStudio workflow dispatch requested successfully."
|
|
224
|
+
python -m pytest ./tests -v --timeout=300
|
|
244
225
|
|
|
245
226
|
build-and-publish-dev:
|
|
246
227
|
# Only publish to TestPyPI when pushing to main (not on PRs or dev branch pushes).
|
|
@@ -259,7 +240,7 @@ jobs:
|
|
|
259
240
|
fetch-depth: 0
|
|
260
241
|
|
|
261
242
|
- name: Set up Python
|
|
262
|
-
uses: actions/setup-python@
|
|
243
|
+
uses: actions/setup-python@v6
|
|
263
244
|
with:
|
|
264
245
|
python-version: '3.11'
|
|
265
246
|
|
|
@@ -351,7 +332,7 @@ jobs:
|
|
|
351
332
|
contents: read
|
|
352
333
|
steps:
|
|
353
334
|
- name: Set up Python ${{ matrix.python-version }}
|
|
354
|
-
uses: actions/setup-python@
|
|
335
|
+
uses: actions/setup-python@v6
|
|
355
336
|
with:
|
|
356
337
|
python-version: ${{ matrix.python-version }}
|
|
357
338
|
allow-prereleases: ${{ matrix.allow-prereleases || false }}
|
|
@@ -16,6 +16,8 @@ jobs:
|
|
|
16
16
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
|
17
17
|
outputs:
|
|
18
18
|
is_main: ${{ steps.check.outputs.is_main }}
|
|
19
|
+
is_dev_release: ${{ steps.check.outputs.is_dev_release }}
|
|
20
|
+
should_run: ${{ steps.check.outputs.should_run }}
|
|
19
21
|
steps:
|
|
20
22
|
- uses: actions/checkout@v4
|
|
21
23
|
with:
|
|
@@ -29,31 +31,53 @@ jobs:
|
|
|
29
31
|
IS_ON_MAIN=$(git merge-base --is-ancestor "${TAG_COMMIT}" origin/main \
|
|
30
32
|
&& echo "true" || echo "false")
|
|
31
33
|
echo "is_main=${IS_ON_MAIN}" >> $GITHUB_OUTPUT
|
|
32
|
-
echo "Tag: ${GITHUB_REF_NAME} commit: ${TAG_COMMIT} on_main: ${IS_ON_MAIN}"
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
# Dev pre-release: a tag NOT on main whose name contains 'dev'
|
|
36
|
+
# (e.g. v1.3.1-dev0). Runs the full pipeline up to the TestPyPI install
|
|
37
|
+
# tests + a GitHub pre-release, then STOPS before the production PyPI
|
|
38
|
+
# publish. A tag off main WITHOUT 'dev' triggers nothing (should_run=false),
|
|
39
|
+
# so accidental/non-dev tags on dev never release.
|
|
40
|
+
IS_DEV_RELEASE=false
|
|
41
|
+
if [ "${IS_ON_MAIN}" != "true" ] && [[ "${GITHUB_REF_NAME}" == *dev* ]]; then
|
|
42
|
+
IS_DEV_RELEASE=true
|
|
43
|
+
fi
|
|
44
|
+
echo "is_dev_release=${IS_DEV_RELEASE}" >> $GITHUB_OUTPUT
|
|
45
|
+
|
|
46
|
+
if [ "${IS_ON_MAIN}" = "true" ] || [ "${IS_DEV_RELEASE}" = "true" ]; then
|
|
47
|
+
SHOULD_RUN=true
|
|
48
|
+
else
|
|
49
|
+
SHOULD_RUN=false
|
|
50
|
+
fi
|
|
51
|
+
echo "should_run=${SHOULD_RUN}" >> $GITHUB_OUTPUT
|
|
52
|
+
echo "Tag: ${GITHUB_REF_NAME} commit: ${TAG_COMMIT} on_main: ${IS_ON_MAIN} dev_release: ${IS_DEV_RELEASE} should_run: ${SHOULD_RUN}"
|
|
53
|
+
|
|
54
|
+
# ── Shared: run tests before any publish (main or dev pre-release) ────────
|
|
35
55
|
test:
|
|
36
56
|
name: Run Tests Before Release
|
|
37
57
|
needs: detect-target
|
|
38
58
|
runs-on: ubuntu-latest
|
|
39
|
-
if: ${{ needs.detect-target.outputs.
|
|
59
|
+
if: ${{ needs.detect-target.outputs.should_run == 'true' }}
|
|
40
60
|
steps:
|
|
41
61
|
- uses: actions/checkout@v4
|
|
42
62
|
|
|
43
|
-
- uses: actions/setup-python@
|
|
63
|
+
- uses: actions/setup-python@v6
|
|
44
64
|
with:
|
|
45
65
|
python-version: '3.11'
|
|
46
66
|
|
|
47
67
|
- name: Install dependencies
|
|
48
68
|
run: |
|
|
49
69
|
python -m pip install --upgrade pip
|
|
50
|
-
|
|
70
|
+
# Install the test extra so pytest, graphviz, torchmetrics,
|
|
71
|
+
# pytorch-lightning and tensorboard are available (several test modules
|
|
72
|
+
# import pytest / use pytest fixtures and cannot run under bare unittest).
|
|
73
|
+
python -m pip install .[utest] --extra-index-url https://download.pytorch.org/whl/cpu
|
|
74
|
+
python -m pip install pytest-timeout
|
|
51
75
|
|
|
52
76
|
- name: Run tests
|
|
53
77
|
run: |
|
|
54
78
|
export WEIGHTSLAB_LOG_LEVEL="DEBUG"
|
|
55
79
|
python -m pip install pytorch_lightning
|
|
56
|
-
python -m unittest discover -s ./
|
|
80
|
+
python -m unittest discover -s ./tests -p "test_*.py" -t . -v
|
|
57
81
|
|
|
58
82
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
59
83
|
# DEV RELEASE — tag on dev branch, not yet merged to main
|
|
@@ -62,9 +86,9 @@ jobs:
|
|
|
62
86
|
|
|
63
87
|
build-and-publish-dev-release:
|
|
64
88
|
name: Build & Publish Dev Release (TestPyPI)
|
|
65
|
-
needs: detect-target
|
|
89
|
+
needs: [detect-target,test]
|
|
66
90
|
runs-on: ubuntu-latest
|
|
67
|
-
if: ${{ needs.detect-target.outputs.
|
|
91
|
+
if: ${{ needs.detect-target.outputs.should_run == 'true' }}
|
|
68
92
|
permissions:
|
|
69
93
|
contents: read
|
|
70
94
|
outputs:
|
|
@@ -74,7 +98,7 @@ jobs:
|
|
|
74
98
|
with:
|
|
75
99
|
fetch-depth: 0
|
|
76
100
|
|
|
77
|
-
- uses: actions/setup-python@
|
|
101
|
+
- uses: actions/setup-python@v6
|
|
78
102
|
with:
|
|
79
103
|
python-version: '3.11'
|
|
80
104
|
|
|
@@ -108,7 +132,7 @@ jobs:
|
|
|
108
132
|
python -m twine upload --repository-url https://test.pypi.org/legacy/ --verbose dist/*
|
|
109
133
|
|
|
110
134
|
- name: Upload build artifacts for release
|
|
111
|
-
uses: actions/upload-artifact@
|
|
135
|
+
uses: actions/upload-artifact@v6
|
|
112
136
|
with:
|
|
113
137
|
name: dev-release-dist
|
|
114
138
|
path: dist/
|
|
@@ -133,7 +157,7 @@ jobs:
|
|
|
133
157
|
permissions:
|
|
134
158
|
contents: read
|
|
135
159
|
steps:
|
|
136
|
-
- uses: actions/setup-python@
|
|
160
|
+
- uses: actions/setup-python@v6
|
|
137
161
|
with:
|
|
138
162
|
python-version: ${{ matrix.python-version }}
|
|
139
163
|
allow-prereleases: ${{ matrix.allow-prereleases || false }}
|
|
@@ -183,9 +207,11 @@ jobs:
|
|
|
183
207
|
print('installed version:', m.version('weightslab'))
|
|
184
208
|
"
|
|
185
209
|
|
|
210
|
+
# Only for a dev pre-release tag (off main, name contains 'dev').
|
|
186
211
|
create-dev-release:
|
|
187
212
|
name: Create GitHub Pre-Release
|
|
188
|
-
needs: [build-and-publish-dev-release, test-install-from-pip-dev-release]
|
|
213
|
+
needs: [detect-target, build-and-publish-dev-release, test-install-from-pip-dev-release]
|
|
214
|
+
if: ${{ needs.detect-target.outputs.is_dev_release == 'true' }}
|
|
189
215
|
runs-on: ubuntu-latest
|
|
190
216
|
permissions:
|
|
191
217
|
contents: write
|
|
@@ -195,7 +221,7 @@ jobs:
|
|
|
195
221
|
fetch-depth: 0
|
|
196
222
|
|
|
197
223
|
- name: Download build artifacts
|
|
198
|
-
uses: actions/download-artifact@
|
|
224
|
+
uses: actions/download-artifact@v7
|
|
199
225
|
with:
|
|
200
226
|
name: dev-release-dist
|
|
201
227
|
path: dist/
|
|
@@ -208,47 +234,142 @@ jobs:
|
|
|
208
234
|
export VERSION_NO_V="${VERSION#v}"
|
|
209
235
|
export PYPI_URL="https://test.pypi.org/project/weightslab/${VERSION_NO_V}/"
|
|
210
236
|
|
|
211
|
-
|
|
237
|
+
# Walk the actual commit graph for the nearest ancestor tag, rather
|
|
238
|
+
# than a lexicographic/semver sort across ALL tags. The old sort
|
|
239
|
+
# could pick an unrelated tag from a diverging branch — e.g. a
|
|
240
|
+
# "v1.3.0-dev0" tag cut on dev after "v1.3.0" was tagged on main
|
|
241
|
+
# sorted ABOVE it, making every real PR since v1.3.0 look "older"
|
|
242
|
+
# than that bogus previous-tag date and get silently filtered out
|
|
243
|
+
# (this is why past releases showed "no pull requests found").
|
|
244
|
+
PREV_TAG=$(git describe --tags --abbrev=0 "${VERSION}^" 2>/dev/null || true)
|
|
212
245
|
if [ -n "$PREV_TAG" ]; then
|
|
213
|
-
|
|
246
|
+
RAW_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || true)
|
|
247
|
+
# Normalize to UTC "Z" form so string comparison against GitHub's
|
|
248
|
+
# mergedAt (also UTC "Z") is valid regardless of the committer's
|
|
249
|
+
# local timezone offset.
|
|
250
|
+
export PREV_TAG_DATE=$(date -u -d "${RAW_DATE:-2020-01-01}" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "2020-01-01T00:00:00Z")
|
|
214
251
|
export GIT_RANGE="${PREV_TAG}..HEAD"
|
|
215
252
|
else
|
|
216
253
|
export PREV_TAG_DATE="2020-01-01T00:00:00Z"
|
|
217
254
|
export GIT_RANGE="HEAD"
|
|
218
255
|
fi
|
|
219
256
|
|
|
220
|
-
export
|
|
221
|
-
|
|
222
|
-
[ -z "$COMMITS" ] && COMMITS="_(no commits found)_"
|
|
257
|
+
export COMMITS_RAW
|
|
258
|
+
COMMITS_RAW=$(git log "${GIT_RANGE}" --no-merges --format="%h%x09%s" 2>/dev/null | head -25 || true)
|
|
223
259
|
|
|
224
260
|
export GIT_AUTHORS
|
|
225
261
|
GIT_AUTHORS=$(git log "${GIT_RANGE}" --format="%an" 2>/dev/null | sort -u | sed 's/^/- /' | head -30 || true)
|
|
226
262
|
|
|
263
|
+
# NOTE: deliberately NOT requesting --json commits here. With
|
|
264
|
+
# --limit 100 that expands into a GraphQL query requesting 100 PRs'
|
|
265
|
+
# worth of commit nodes, which reliably exceeds GitHub's 500,000
|
|
266
|
+
# node budget and makes `gh` print a plain-text GraphQL error
|
|
267
|
+
# instead of JSON — json.loads() below then fails, prs_data
|
|
268
|
+
# silently becomes [], and every release note says "no pull
|
|
269
|
+
# requests found" regardless of the date filter. Commits are
|
|
270
|
+
# fetched below, one lightweight call per PR, only for the small
|
|
271
|
+
# number of PRs that actually match this release.
|
|
227
272
|
export PRS_JSON
|
|
228
273
|
PRS_JSON=$(gh pr list --state merged --base "dev" --limit 100 \
|
|
229
274
|
--json number,title,mergedAt,url,author,body \
|
|
230
275
|
2>/dev/null || echo "[]")
|
|
231
276
|
|
|
232
277
|
python3 << 'PYEOF'
|
|
233
|
-
import os, json
|
|
278
|
+
import os, json, re, importlib.util, subprocess
|
|
234
279
|
version = os.environ["VERSION"]
|
|
235
280
|
pypi_url = os.environ["PYPI_URL"]
|
|
236
281
|
prev_date = os.environ.get("PREV_TAG_DATE", "2020-01-01")
|
|
237
|
-
|
|
282
|
+
commits_raw = os.environ.get("COMMITS_RAW", "")
|
|
238
283
|
git_authors = os.environ.get("GIT_AUTHORS", "")
|
|
239
284
|
try:
|
|
240
285
|
prs_data = json.loads(os.environ.get("PRS_JSON", "[]"))
|
|
241
286
|
except Exception:
|
|
242
287
|
prs_data = []
|
|
288
|
+
|
|
289
|
+
_README_RE = re.compile(r'^update\s+readme(\.md)?\s*$', re.IGNORECASE)
|
|
290
|
+
|
|
291
|
+
def _strip_pr_suffix(head):
|
|
292
|
+
return re.sub(r'\s*\(#\d+\)\s*$', '', head).strip()
|
|
293
|
+
|
|
294
|
+
def _collapse_readme(entries):
|
|
295
|
+
"""entries: list of (oid_or_None, head) tuples, in original order.
|
|
296
|
+
Collapse every bare "Update README[.md]" commit into a single
|
|
297
|
+
"Update README (n)" line at the position of its first occurrence —
|
|
298
|
+
these are near-duplicate housekeeping commits with no release signal."""
|
|
299
|
+
out, count, placeholder_idx = [], 0, None
|
|
300
|
+
for oid, head in entries:
|
|
301
|
+
if _README_RE.match(_strip_pr_suffix(head)):
|
|
302
|
+
count += 1
|
|
303
|
+
if placeholder_idx is None:
|
|
304
|
+
placeholder_idx = len(out)
|
|
305
|
+
out.append(None)
|
|
306
|
+
continue
|
|
307
|
+
out.append((oid, head))
|
|
308
|
+
if placeholder_idx is not None:
|
|
309
|
+
label = "Update README" if count == 1 else f"Update README ({count})"
|
|
310
|
+
out[placeholder_idx] = (None, label)
|
|
311
|
+
return out
|
|
312
|
+
|
|
313
|
+
def _format_entries(entries, indent=""):
|
|
314
|
+
return [f"{indent}- `{oid}` {head}" if oid else f"{indent}- {head}" for oid, head in entries]
|
|
315
|
+
|
|
243
316
|
def _pr_entry(pr):
|
|
244
|
-
line = f"- [#{pr['number']}]({pr['url']}) {pr['title']} — {pr['mergedAt'][:10]}"
|
|
245
317
|
desc = " ".join((pr.get("body") or "").split()) # collapse newlines/whitespace
|
|
246
|
-
if desc:
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
return
|
|
318
|
+
if not desc:
|
|
319
|
+
desc = pr["title"]
|
|
320
|
+
if len(desc) > 512:
|
|
321
|
+
desc = desc[:509].rstrip() + "..."
|
|
322
|
+
return f"- [PR #{pr['number']}]({pr['url']}): {desc}"
|
|
323
|
+
|
|
324
|
+
def _fetch_pr_commits(number):
|
|
325
|
+
# One lightweight call per matched PR (see the note above the
|
|
326
|
+
# PRS_JSON fetch for why this isn't batched into the list query).
|
|
327
|
+
try:
|
|
328
|
+
out = subprocess.run(
|
|
329
|
+
["gh", "pr", "view", str(number), "--json", "commits"],
|
|
330
|
+
capture_output=True, text=True, timeout=30,
|
|
331
|
+
)
|
|
332
|
+
if out.returncode != 0:
|
|
333
|
+
return []
|
|
334
|
+
return json.loads(out.stdout).get("commits") or []
|
|
335
|
+
except Exception:
|
|
336
|
+
return []
|
|
337
|
+
|
|
251
338
|
filtered = [pr for pr in prs_data if pr.get("mergedAt", "") > prev_date]
|
|
339
|
+
# "What's Changed precisely": list each merged PR's own developer commits,
|
|
340
|
+
# NOT the squashed/merge/chore commits that land on the release branch
|
|
341
|
+
# (those are redundant with the PR list above and not useful).
|
|
342
|
+
_seen_commits = set()
|
|
343
|
+
_commit_blocks = []
|
|
344
|
+
for pr in filtered:
|
|
345
|
+
raw_entries = []
|
|
346
|
+
for c in _fetch_pr_commits(pr["number"]):
|
|
347
|
+
oid = (c.get("oid") or "")[:7]
|
|
348
|
+
head = (c.get("messageHeadline") or "").strip()
|
|
349
|
+
if not head or head.startswith("Merge "):
|
|
350
|
+
continue
|
|
351
|
+
key = (oid, head)
|
|
352
|
+
if key in _seen_commits:
|
|
353
|
+
continue
|
|
354
|
+
_seen_commits.add(key)
|
|
355
|
+
raw_entries.append((oid, head))
|
|
356
|
+
commit_lines = _format_entries(_collapse_readme(raw_entries), indent=" ")
|
|
357
|
+
if commit_lines:
|
|
358
|
+
_commit_blocks.append(
|
|
359
|
+
f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(commit_lines)
|
|
360
|
+
)
|
|
361
|
+
# Fall back to the raw git log only when no PR commits are available.
|
|
362
|
+
if _commit_blocks:
|
|
363
|
+
commits_section = "\n\n".join(_commit_blocks)
|
|
364
|
+
else:
|
|
365
|
+
fallback_entries = []
|
|
366
|
+
for line in commits_raw.splitlines():
|
|
367
|
+
if "\t" not in line:
|
|
368
|
+
continue
|
|
369
|
+
oid, head = line.split("\t", 1)
|
|
370
|
+
fallback_entries.append((oid, head))
|
|
371
|
+
fallback_entries = _collapse_readme(fallback_entries)
|
|
372
|
+
commits_section = "\n".join(_format_entries(fallback_entries)) if fallback_entries else "_(no commits found)_"
|
|
252
373
|
if filtered:
|
|
253
374
|
prs_lines = "\n".join(_pr_entry(pr) for pr in filtered)
|
|
254
375
|
seen, clabels = set(), []
|
|
@@ -261,7 +382,23 @@ jobs:
|
|
|
261
382
|
else:
|
|
262
383
|
prs_lines = "_(no pull requests found since last release)_"
|
|
263
384
|
contributors = git_authors or "_(no contributors found)_"
|
|
385
|
+
|
|
386
|
+
# CLI banner (weightslab/art.py), loaded as a standalone file so we
|
|
387
|
+
# don't pull in the full package (and its heavy optional deps) just
|
|
388
|
+
# to print a logo. ANSI color codes are stripped (Markdown can't render
|
|
389
|
+
# them); the box-drawing/ASCII art itself renders fine in a code fence.
|
|
390
|
+
banner_block = ""
|
|
391
|
+
try:
|
|
392
|
+
spec = importlib.util.spec_from_file_location("wl_art", "weightslab/art.py")
|
|
393
|
+
wl_art = importlib.util.module_from_spec(spec)
|
|
394
|
+
spec.loader.exec_module(wl_art)
|
|
395
|
+
plain_banner = re.sub(r'\x1b\[[0-9;]*m', '', wl_art._BANNER)
|
|
396
|
+
banner_block = f"```text\n{plain_banner.strip(chr(10))}\n```\n\n"
|
|
397
|
+
except Exception:
|
|
398
|
+
pass
|
|
399
|
+
|
|
264
400
|
body = (
|
|
401
|
+
banner_block +
|
|
265
402
|
"## **Weightslab**\n\n"
|
|
266
403
|
"Follow us on [LinkedIn](https://www.linkedin.com/company/graybx-com/)"
|
|
267
404
|
" | [Graybx](https://www.graybx.com/)\n\n"
|
|
@@ -276,12 +413,12 @@ jobs:
|
|
|
276
413
|
"Happy Training!\n\n"
|
|
277
414
|
"---\n\n"
|
|
278
415
|
"### What's Changed precisely:\n\n"
|
|
279
|
-
f"{
|
|
416
|
+
f"{commits_section}\n\n"
|
|
280
417
|
"---\n\n"
|
|
281
418
|
"### Thank you!\n\n"
|
|
282
419
|
f"{contributors}\n"
|
|
283
420
|
)
|
|
284
|
-
with open("RELEASE_NOTES.md", "w") as f:
|
|
421
|
+
with open("RELEASE_NOTES.md", "w", encoding="utf-8") as f:
|
|
285
422
|
f.write(body)
|
|
286
423
|
PYEOF
|
|
287
424
|
|
|
@@ -303,7 +440,7 @@ jobs:
|
|
|
303
440
|
|
|
304
441
|
build-and-publish-main:
|
|
305
442
|
name: Build & Publish Main (PyPI)
|
|
306
|
-
needs: [detect-target]
|
|
443
|
+
needs: [test-install-from-pip-dev-release, detect-target]
|
|
307
444
|
runs-on: ubuntu-latest
|
|
308
445
|
if: ${{ needs.detect-target.outputs.is_main == 'true' }}
|
|
309
446
|
permissions:
|
|
@@ -315,7 +452,7 @@ jobs:
|
|
|
315
452
|
with:
|
|
316
453
|
fetch-depth: 0
|
|
317
454
|
|
|
318
|
-
- uses: actions/setup-python@
|
|
455
|
+
- uses: actions/setup-python@v6
|
|
319
456
|
with:
|
|
320
457
|
python-version: '3.11'
|
|
321
458
|
|
|
@@ -349,7 +486,7 @@ jobs:
|
|
|
349
486
|
python -m twine upload dist/* --non-interactive --verbose
|
|
350
487
|
|
|
351
488
|
- name: Upload build artifacts for release
|
|
352
|
-
uses: actions/upload-artifact@
|
|
489
|
+
uses: actions/upload-artifact@v6
|
|
353
490
|
with:
|
|
354
491
|
name: main-release-dist
|
|
355
492
|
path: dist/
|
|
@@ -367,7 +504,7 @@ jobs:
|
|
|
367
504
|
permissions:
|
|
368
505
|
contents: read
|
|
369
506
|
steps:
|
|
370
|
-
- uses: actions/setup-python@
|
|
507
|
+
- uses: actions/setup-python@v6
|
|
371
508
|
with:
|
|
372
509
|
python-version: ${{ matrix.python-version }}
|
|
373
510
|
|
|
@@ -417,7 +554,7 @@ jobs:
|
|
|
417
554
|
|
|
418
555
|
create-main-release:
|
|
419
556
|
name: Create GitHub Release
|
|
420
|
-
needs: [
|
|
557
|
+
needs: [test-install-from-pip-main]
|
|
421
558
|
runs-on: ubuntu-latest
|
|
422
559
|
permissions:
|
|
423
560
|
contents: write
|
|
@@ -427,7 +564,7 @@ jobs:
|
|
|
427
564
|
fetch-depth: 0
|
|
428
565
|
|
|
429
566
|
- name: Download build artifacts
|
|
430
|
-
uses: actions/download-artifact@
|
|
567
|
+
uses: actions/download-artifact@v7
|
|
431
568
|
with:
|
|
432
569
|
name: main-release-dist
|
|
433
570
|
path: dist/
|
|
@@ -440,47 +577,142 @@ jobs:
|
|
|
440
577
|
export VERSION_NO_V="${VERSION#v}"
|
|
441
578
|
export PYPI_URL="https://pypi.org/project/weightslab/${VERSION_NO_V}/"
|
|
442
579
|
|
|
443
|
-
|
|
580
|
+
# Walk the actual commit graph for the nearest ancestor tag, rather
|
|
581
|
+
# than a lexicographic/semver sort across ALL tags. The old sort
|
|
582
|
+
# could pick an unrelated tag from a diverging branch — e.g. a
|
|
583
|
+
# "v1.3.0-dev0" tag cut on dev after "v1.3.0" was tagged on main
|
|
584
|
+
# sorted ABOVE it, making every real PR since v1.3.0 look "older"
|
|
585
|
+
# than that bogus previous-tag date and get silently filtered out
|
|
586
|
+
# (this is why past releases showed "no pull requests found").
|
|
587
|
+
PREV_TAG=$(git describe --tags --abbrev=0 "${VERSION}^" 2>/dev/null || true)
|
|
444
588
|
if [ -n "$PREV_TAG" ]; then
|
|
445
|
-
|
|
589
|
+
RAW_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || true)
|
|
590
|
+
# Normalize to UTC "Z" form so string comparison against GitHub's
|
|
591
|
+
# mergedAt (also UTC "Z") is valid regardless of the committer's
|
|
592
|
+
# local timezone offset.
|
|
593
|
+
export PREV_TAG_DATE=$(date -u -d "${RAW_DATE:-2020-01-01}" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "2020-01-01T00:00:00Z")
|
|
446
594
|
export GIT_RANGE="${PREV_TAG}..HEAD"
|
|
447
595
|
else
|
|
448
596
|
export PREV_TAG_DATE="2020-01-01T00:00:00Z"
|
|
449
597
|
export GIT_RANGE="HEAD"
|
|
450
598
|
fi
|
|
451
599
|
|
|
452
|
-
export
|
|
453
|
-
|
|
454
|
-
[ -z "$COMMITS" ] && COMMITS="_(no commits found)_"
|
|
600
|
+
export COMMITS_RAW
|
|
601
|
+
COMMITS_RAW=$(git log "${GIT_RANGE}" --no-merges --format="%h%x09%s" 2>/dev/null | head -25 || true)
|
|
455
602
|
|
|
456
603
|
export GIT_AUTHORS
|
|
457
604
|
GIT_AUTHORS=$(git log "${GIT_RANGE}" --format="%an" 2>/dev/null | sort -u | sed 's/^/- /' | head -30 || true)
|
|
458
605
|
|
|
606
|
+
# NOTE: deliberately NOT requesting --json commits here. With
|
|
607
|
+
# --limit 100 that expands into a GraphQL query requesting 100 PRs'
|
|
608
|
+
# worth of commit nodes, which reliably exceeds GitHub's 500,000
|
|
609
|
+
# node budget and makes `gh` print a plain-text GraphQL error
|
|
610
|
+
# instead of JSON — json.loads() below then fails, prs_data
|
|
611
|
+
# silently becomes [], and every release note says "no pull
|
|
612
|
+
# requests found" regardless of the date filter. Commits are
|
|
613
|
+
# fetched below, one lightweight call per PR, only for the small
|
|
614
|
+
# number of PRs that actually match this release.
|
|
459
615
|
export PRS_JSON
|
|
460
616
|
PRS_JSON=$(gh pr list --state merged --base "main" --limit 100 \
|
|
461
617
|
--json number,title,mergedAt,url,author,body \
|
|
462
618
|
2>/dev/null || echo "[]")
|
|
463
619
|
|
|
464
620
|
python3 << 'PYEOF'
|
|
465
|
-
import os, json
|
|
621
|
+
import os, json, re, importlib.util, subprocess
|
|
466
622
|
version = os.environ["VERSION"]
|
|
467
623
|
pypi_url = os.environ["PYPI_URL"]
|
|
468
624
|
prev_date = os.environ.get("PREV_TAG_DATE", "2020-01-01")
|
|
469
|
-
|
|
625
|
+
commits_raw = os.environ.get("COMMITS_RAW", "")
|
|
470
626
|
git_authors = os.environ.get("GIT_AUTHORS", "")
|
|
471
627
|
try:
|
|
472
628
|
prs_data = json.loads(os.environ.get("PRS_JSON", "[]"))
|
|
473
629
|
except Exception:
|
|
474
630
|
prs_data = []
|
|
631
|
+
|
|
632
|
+
_README_RE = re.compile(r'^update\s+readme(\.md)?\s*$', re.IGNORECASE)
|
|
633
|
+
|
|
634
|
+
def _strip_pr_suffix(head):
|
|
635
|
+
return re.sub(r'\s*\(#\d+\)\s*$', '', head).strip()
|
|
636
|
+
|
|
637
|
+
def _collapse_readme(entries):
|
|
638
|
+
"""entries: list of (oid_or_None, head) tuples, in original order.
|
|
639
|
+
Collapse every bare "Update README[.md]" commit into a single
|
|
640
|
+
"Update README (n)" line at the position of its first occurrence —
|
|
641
|
+
these are near-duplicate housekeeping commits with no release signal."""
|
|
642
|
+
out, count, placeholder_idx = [], 0, None
|
|
643
|
+
for oid, head in entries:
|
|
644
|
+
if _README_RE.match(_strip_pr_suffix(head)):
|
|
645
|
+
count += 1
|
|
646
|
+
if placeholder_idx is None:
|
|
647
|
+
placeholder_idx = len(out)
|
|
648
|
+
out.append(None)
|
|
649
|
+
continue
|
|
650
|
+
out.append((oid, head))
|
|
651
|
+
if placeholder_idx is not None:
|
|
652
|
+
label = "Update README" if count == 1 else f"Update README ({count})"
|
|
653
|
+
out[placeholder_idx] = (None, label)
|
|
654
|
+
return out
|
|
655
|
+
|
|
656
|
+
def _format_entries(entries, indent=""):
|
|
657
|
+
return [f"{indent}- `{oid}` {head}" if oid else f"{indent}- {head}" for oid, head in entries]
|
|
658
|
+
|
|
475
659
|
def _pr_entry(pr):
|
|
476
|
-
line = f"- [#{pr['number']}]({pr['url']}) {pr['title']} — {pr['mergedAt'][:10]}"
|
|
477
660
|
desc = " ".join((pr.get("body") or "").split()) # collapse newlines/whitespace
|
|
478
|
-
if desc:
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return
|
|
661
|
+
if not desc:
|
|
662
|
+
desc = pr["title"]
|
|
663
|
+
if len(desc) > 512:
|
|
664
|
+
desc = desc[:509].rstrip() + "..."
|
|
665
|
+
return f"- [PR #{pr['number']}]({pr['url']}): {desc}"
|
|
666
|
+
|
|
667
|
+
def _fetch_pr_commits(number):
|
|
668
|
+
# One lightweight call per matched PR (see the note above the
|
|
669
|
+
# PRS_JSON fetch for why this isn't batched into the list query).
|
|
670
|
+
try:
|
|
671
|
+
out = subprocess.run(
|
|
672
|
+
["gh", "pr", "view", str(number), "--json", "commits"],
|
|
673
|
+
capture_output=True, text=True, timeout=30,
|
|
674
|
+
)
|
|
675
|
+
if out.returncode != 0:
|
|
676
|
+
return []
|
|
677
|
+
return json.loads(out.stdout).get("commits") or []
|
|
678
|
+
except Exception:
|
|
679
|
+
return []
|
|
680
|
+
|
|
483
681
|
filtered = [pr for pr in prs_data if pr.get("mergedAt", "") > prev_date]
|
|
682
|
+
# "What's Changed precisely": list each merged PR's own developer commits,
|
|
683
|
+
# NOT the squashed/merge/chore commits that land on the release branch
|
|
684
|
+
# (those are redundant with the PR list above and not useful).
|
|
685
|
+
_seen_commits = set()
|
|
686
|
+
_commit_blocks = []
|
|
687
|
+
for pr in filtered:
|
|
688
|
+
raw_entries = []
|
|
689
|
+
for c in _fetch_pr_commits(pr["number"]):
|
|
690
|
+
oid = (c.get("oid") or "")[:7]
|
|
691
|
+
head = (c.get("messageHeadline") or "").strip()
|
|
692
|
+
if not head or head.startswith("Merge "):
|
|
693
|
+
continue
|
|
694
|
+
key = (oid, head)
|
|
695
|
+
if key in _seen_commits:
|
|
696
|
+
continue
|
|
697
|
+
_seen_commits.add(key)
|
|
698
|
+
raw_entries.append((oid, head))
|
|
699
|
+
commit_lines = _format_entries(_collapse_readme(raw_entries), indent=" ")
|
|
700
|
+
if commit_lines:
|
|
701
|
+
_commit_blocks.append(
|
|
702
|
+
f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(commit_lines)
|
|
703
|
+
)
|
|
704
|
+
# Fall back to the raw git log only when no PR commits are available.
|
|
705
|
+
if _commit_blocks:
|
|
706
|
+
commits_section = "\n\n".join(_commit_blocks)
|
|
707
|
+
else:
|
|
708
|
+
fallback_entries = []
|
|
709
|
+
for line in commits_raw.splitlines():
|
|
710
|
+
if "\t" not in line:
|
|
711
|
+
continue
|
|
712
|
+
oid, head = line.split("\t", 1)
|
|
713
|
+
fallback_entries.append((oid, head))
|
|
714
|
+
fallback_entries = _collapse_readme(fallback_entries)
|
|
715
|
+
commits_section = "\n".join(_format_entries(fallback_entries)) if fallback_entries else "_(no commits found)_"
|
|
484
716
|
if filtered:
|
|
485
717
|
prs_lines = "\n".join(_pr_entry(pr) for pr in filtered)
|
|
486
718
|
seen, clabels = set(), []
|
|
@@ -493,7 +725,23 @@ jobs:
|
|
|
493
725
|
else:
|
|
494
726
|
prs_lines = "_(no pull requests found since last release)_"
|
|
495
727
|
contributors = git_authors or "_(no contributors found)_"
|
|
728
|
+
|
|
729
|
+
# CLI banner (weightslab/art.py), loaded as a standalone file so we
|
|
730
|
+
# don't pull in the full package (and its heavy optional deps) just
|
|
731
|
+
# to print a logo. ANSI color codes are stripped (Markdown can't render
|
|
732
|
+
# them); the box-drawing/ASCII art itself renders fine in a code fence.
|
|
733
|
+
banner_block = ""
|
|
734
|
+
try:
|
|
735
|
+
spec = importlib.util.spec_from_file_location("wl_art", "weightslab/art.py")
|
|
736
|
+
wl_art = importlib.util.module_from_spec(spec)
|
|
737
|
+
spec.loader.exec_module(wl_art)
|
|
738
|
+
plain_banner = re.sub(r'\x1b\[[0-9;]*m', '', wl_art._BANNER)
|
|
739
|
+
banner_block = f"```text\n{plain_banner.strip(chr(10))}\n```\n\n"
|
|
740
|
+
except Exception:
|
|
741
|
+
pass
|
|
742
|
+
|
|
496
743
|
body = (
|
|
744
|
+
banner_block +
|
|
497
745
|
"## **Weightslab**\n\n"
|
|
498
746
|
"Follow us on [LinkedIn](https://www.linkedin.com/company/graybx-com/)"
|
|
499
747
|
" | [Graybx](https://www.graybx.com/)\n\n"
|
|
@@ -508,12 +756,12 @@ jobs:
|
|
|
508
756
|
"Happy Training!\n\n"
|
|
509
757
|
"---\n\n"
|
|
510
758
|
"### What's Changed precisely:\n\n"
|
|
511
|
-
f"{
|
|
759
|
+
f"{commits_section}\n\n"
|
|
512
760
|
"---\n\n"
|
|
513
761
|
"### Thank you!\n\n"
|
|
514
762
|
f"{contributors}\n"
|
|
515
763
|
)
|
|
516
|
-
with open("RELEASE_NOTES.md", "w") as f:
|
|
764
|
+
with open("RELEASE_NOTES.md", "w", encoding="utf-8") as f:
|
|
517
765
|
f.write(body)
|
|
518
766
|
PYEOF
|
|
519
767
|
|