aimodelshare 0.3.62__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.
- aimodelshare-0.3.62/.github/workflows/ai_lead_engineer_app_test.yml +98 -0
- aimodelshare-0.3.62/.github/workflows/aimodelshare-tests.yml +84 -0
- aimodelshare-0.3.62/.github/workflows/bootstrap-terraform.yml +149 -0
- aimodelshare-0.3.62/.github/workflows/cleanup-test-resources.yml +104 -0
- aimodelshare-0.3.62/.github/workflows/deploy-infra.yml +221 -0
- aimodelshare-0.3.62/.github/workflows/deploy_gradio_apps.yml +469 -0
- aimodelshare-0.3.62/.github/workflows/destroy-infra.yml +114 -0
- aimodelshare-0.3.62/.github/workflows/gradio-session-login-integration.yml +47 -0
- aimodelshare-0.3.62/.github/workflows/kpi-dict-submissioncount-integration.yml +46 -0
- aimodelshare-0.3.62/.github/workflows/mc-comprehensive-integration-test.yml +116 -0
- aimodelshare-0.3.62/.github/workflows/mc-rank-integration-test.yml +122 -0
- aimodelshare-0.3.62/.github/workflows/mc_auth_debug.yml +75 -0
- aimodelshare-0.3.62/.github/workflows/moral_compass_auth_test.yml +78 -0
- aimodelshare-0.3.62/.github/workflows/playground-integration-tests.yml +603 -0
- aimodelshare-0.3.62/.github/workflows/publish-lambda-layers.yml +556 -0
- aimodelshare-0.3.62/.github/workflows/pypi-manual-publish.yml +151 -0
- aimodelshare-0.3.62/.github/workflows/sessionid-kpi-workflow.yml +48 -0
- aimodelshare-0.3.62/.github/workflows/test-colab-install.yml +122 -0
- aimodelshare-0.3.62/.github/workflows/test-colab-simulated.yml +90 -0
- aimodelshare-0.3.62/.github/workflows/unit-tests.yml +77 -0
- aimodelshare-0.3.62/.gitignore +174 -0
- aimodelshare-0.3.62/ACTIVITIES_7_8_9_IMPLEMENTATION.md +228 -0
- aimodelshare-0.3.62/BIAS_DETECTIVE_AUTH_UPDATE.md +229 -0
- aimodelshare-0.3.62/BIAS_DETECTIVE_ENHANCEMENTS.md +194 -0
- aimodelshare-0.3.62/BIAS_DETECTIVE_RANK_FIX_SUMMARY.md +215 -0
- aimodelshare-0.3.62/BIAS_DETECTIVE_TASK_TRACKING.md +189 -0
- aimodelshare-0.3.62/BIAS_DETECTIVE_TRANSITIONS_IMPLEMENTATION.md +185 -0
- aimodelshare-0.3.62/BIAS_DETECTIVE_V2_IMPLEMENTATION.md +624 -0
- aimodelshare-0.3.62/CHANGES_SUMMARY.md +225 -0
- aimodelshare-0.3.62/CLEANUP_RESOURCES.md +243 -0
- aimodelshare-0.3.62/CLOUD_RUN_DEPLOYMENT.md +273 -0
- aimodelshare-0.3.62/CODE_REVIEW.md +113 -0
- aimodelshare-0.3.62/COMPLETED_TASK_IDS_IMPLEMENTATION.md +167 -0
- aimodelshare-0.3.62/Dockerfile +23 -0
- aimodelshare-0.3.62/GRADIO_APPS_IMPLEMENTATION.md +245 -0
- aimodelshare-0.3.62/IMPLEMENTATION_SUMMARY.md +300 -0
- aimodelshare-0.3.62/IMPLEMENTATION_SUMMARY_ACTIVITIES_7_8_9.md +212 -0
- aimodelshare-0.3.62/IMPLEMENTATION_SUMMARY_DIAGNOSTICS.md +174 -0
- aimodelshare-0.3.62/IMPLEMENTATION_SUMMARY_READINESS_GATING.md +289 -0
- aimodelshare-0.3.62/IMPLEMENTATION_SUMMARY_REGION_AWARE.md +177 -0
- aimodelshare-0.3.62/IMPLEMENTATION_SUMMARY_UX_ENHANCEMENTS.md +466 -0
- aimodelshare-0.3.62/INTEGRATION_TEST_IMPLEMENTATION_SUMMARY.md +304 -0
- aimodelshare-0.3.62/KPI_IMPROVEMENTS_SUMMARY.md +194 -0
- aimodelshare-0.3.62/LICENSE +5 -0
- aimodelshare-0.3.62/MANIFEST.in +3 -0
- aimodelshare-0.3.62/METADATA_FIX_DOCUMENTATION.md +331 -0
- aimodelshare-0.3.62/MODEL_BUILDING_GAME_REFACTOR_PLAN.md +300 -0
- aimodelshare-0.3.62/MODEL_IMPROVEMENT_APPS_FIX.md +159 -0
- aimodelshare-0.3.62/MODERNIZATION_SUMMARY.md +127 -0
- aimodelshare-0.3.62/MORAL_COMPASS_INTEGRATION.md +332 -0
- aimodelshare-0.3.62/NAVIGATION_FIX_SUMMARY.md +73 -0
- aimodelshare-0.3.62/PKG-INFO +298 -0
- aimodelshare-0.3.62/PLAYGROUND_TEST_ISOLATION.md +202 -0
- aimodelshare-0.3.62/PREPROCESSOR_DIAGNOSTICS.md +259 -0
- aimodelshare-0.3.62/PR_SUMMARY.md +240 -0
- aimodelshare-0.3.62/README.md +239 -0
- aimodelshare-0.3.62/RESTORE_V0164_PR_DESCRIPTION.md +182 -0
- aimodelshare-0.3.62/TEAM_PERSISTENCE_IMPLEMENTATION.md +280 -0
- aimodelshare-0.3.62/TEST_MODE_DOCUMENTATION.md +253 -0
- aimodelshare-0.3.62/aimodelshare/README.md +26 -0
- aimodelshare-0.3.62/aimodelshare/__init__.py +100 -0
- aimodelshare-0.3.62/aimodelshare/aimsonnx.py +2381 -0
- aimodelshare-0.3.62/aimodelshare/api.py +836 -0
- aimodelshare-0.3.62/aimodelshare/auth.py +163 -0
- aimodelshare-0.3.62/aimodelshare/aws.py +511 -0
- aimodelshare-0.3.62/aimodelshare/aws_client.py +173 -0
- aimodelshare-0.3.62/aimodelshare/base_image.py +154 -0
- aimodelshare-0.3.62/aimodelshare/bucketpolicy.py +106 -0
- aimodelshare-0.3.62/aimodelshare/color_mappings/color_mapping_keras.csv +121 -0
- aimodelshare-0.3.62/aimodelshare/color_mappings/color_mapping_pytorch.csv +117 -0
- aimodelshare-0.3.62/aimodelshare/containerisation.py +244 -0
- aimodelshare-0.3.62/aimodelshare/containerization.py +712 -0
- aimodelshare-0.3.62/aimodelshare/containerization_templates/Dockerfile.txt +8 -0
- aimodelshare-0.3.62/aimodelshare/containerization_templates/Dockerfile_PySpark.txt +23 -0
- aimodelshare-0.3.62/aimodelshare/containerization_templates/buildspec.txt +14 -0
- aimodelshare-0.3.62/aimodelshare/containerization_templates/lambda_function.txt +40 -0
- aimodelshare-0.3.62/aimodelshare/custom_approach/__init__.py +1 -0
- aimodelshare-0.3.62/aimodelshare/custom_approach/lambda_function.py +17 -0
- aimodelshare-0.3.62/aimodelshare/custom_eval_metrics.py +103 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/__init__.py +0 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/data_sharing_templates/Dockerfile.txt +3 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/data_sharing_templates/__init__.py +1 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/data_sharing_templates/buildspec.txt +15 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/data_sharing_templates/codebuild_policies.txt +129 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/data_sharing_templates/codebuild_trust_relationship.txt +12 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/download_data.py +620 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/share_data.py +373 -0
- aimodelshare-0.3.62/aimodelshare/data_sharing/utils.py +8 -0
- aimodelshare-0.3.62/aimodelshare/deploy_custom_lambda.py +246 -0
- aimodelshare-0.3.62/aimodelshare/documentation/Makefile +20 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/__init__.py +28 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/_version.py +2 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/breadcrumbs.html +70 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/layout.html +172 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/search.html +50 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/searchbox.html +14 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css +2 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css.map +1 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css +2751 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css.map +1 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css +2 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css.map +1 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.eot +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.svg +32 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.ttf +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff2 +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/static/js/theme.js +68 -0
- aimodelshare-0.3.62/aimodelshare/documentation/karma_sphinx_theme/theme.conf +9 -0
- aimodelshare-0.3.62/aimodelshare/documentation/make.bat +35 -0
- aimodelshare-0.3.62/aimodelshare/documentation/requirements.txt +2 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/about.rst +18 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/advanced_features.rst +137 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/competition.rst +218 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/conf.py +58 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/create_credentials.rst +86 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/example_notebooks.rst +132 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/functions.rst +151 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/gettingstarted.rst +390 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/creds1.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/creds2.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/creds3.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/creds4.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/creds5.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/creds_file_example.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/images/predict_tab.png +0 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/index.rst +110 -0
- aimodelshare-0.3.62/aimodelshare/documentation/source/modelplayground.rst +132 -0
- aimodelshare-0.3.62/aimodelshare/exceptions.py +11 -0
- aimodelshare-0.3.62/aimodelshare/generatemodelapi.py +1270 -0
- aimodelshare-0.3.62/aimodelshare/iam/codebuild_policy.txt +129 -0
- aimodelshare-0.3.62/aimodelshare/iam/codebuild_trust_relationship.txt +12 -0
- aimodelshare-0.3.62/aimodelshare/iam/lambda_policy.txt +15 -0
- aimodelshare-0.3.62/aimodelshare/iam/lambda_trust_relationship.txt +12 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/__init__.py +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/api_json.txt +155 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/auth/policy.txt +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/auth/role.txt +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/eval/policy.txt +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/eval/role.txt +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/function/policy.txt +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/function/role.txt +1 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/integration_response.txt +5 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/lambda_policy_1.txt +15 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/lambda_policy_2.txt +8 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/lambda_role_1.txt +12 -0
- aimodelshare-0.3.62/aimodelshare/json_templates/lambda_role_2.txt +16 -0
- aimodelshare-0.3.62/aimodelshare/leaderboard.py +174 -0
- aimodelshare-0.3.62/aimodelshare/main/1.txt +132 -0
- aimodelshare-0.3.62/aimodelshare/main/1B.txt +112 -0
- aimodelshare-0.3.62/aimodelshare/main/2.txt +153 -0
- aimodelshare-0.3.62/aimodelshare/main/3.txt +134 -0
- aimodelshare-0.3.62/aimodelshare/main/4.txt +128 -0
- aimodelshare-0.3.62/aimodelshare/main/5.txt +109 -0
- aimodelshare-0.3.62/aimodelshare/main/6.txt +105 -0
- aimodelshare-0.3.62/aimodelshare/main/7.txt +144 -0
- aimodelshare-0.3.62/aimodelshare/main/8.txt +142 -0
- aimodelshare-0.3.62/aimodelshare/main/__init__.py +1 -0
- aimodelshare-0.3.62/aimodelshare/main/authorization.txt +275 -0
- aimodelshare-0.3.62/aimodelshare/main/eval_classification.txt +79 -0
- aimodelshare-0.3.62/aimodelshare/main/eval_lambda.txt +1709 -0
- aimodelshare-0.3.62/aimodelshare/main/eval_regression.txt +80 -0
- aimodelshare-0.3.62/aimodelshare/main/lambda_function.txt +8 -0
- aimodelshare-0.3.62/aimodelshare/main/nst.txt +149 -0
- aimodelshare-0.3.62/aimodelshare/model.py +1543 -0
- aimodelshare-0.3.62/aimodelshare/modeluser.py +215 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/README.md +408 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/__init__.py +75 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/_version.py +3 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/api_client.py +689 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/__init__.py +77 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/ai_consequences.py +550 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/bias_detective_part1.py +2722 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/bias_detective_part2.py +2465 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/ethical_revelation.py +988 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/fairness_fixer.py +1869 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/judge.py +875 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/justice_equity_upgrade.py +853 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/mc_integration_helpers.py +302 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/model_building_app_ca.py +4462 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/model_building_app_en.py +4379 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/model_building_app_es.py +4462 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/model_building_game.py +4380 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/model_building_game_beginner.py +687 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/moral_compass_challenge.py +958 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/session_auth.py +254 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/shared_activity_styles.css +349 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/tutorial.py +481 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/apps/what_is_ai.py +862 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/challenge.py +446 -0
- aimodelshare-0.3.62/aimodelshare/moral_compass/config.py +187 -0
- aimodelshare-0.3.62/aimodelshare/placeholders/model.onnx +0 -0
- aimodelshare-0.3.62/aimodelshare/placeholders/preprocessor.zip +0 -0
- aimodelshare-0.3.62/aimodelshare/playground.py +1968 -0
- aimodelshare-0.3.62/aimodelshare/postprocessormodules.py +157 -0
- aimodelshare-0.3.62/aimodelshare/preprocessormodules.py +373 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/1.txt +195 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/1B.txt +181 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/2.txt +220 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/3.txt +204 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/4.txt +187 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/5.txt +178 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/6.txt +174 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/7.txt +211 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/8.txt +206 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/__init__.py +1 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/authorization.txt +258 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/eval_classification.txt +79 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/eval_lambda.txt +1441 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/eval_regression.txt +80 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/lambda_function.txt +8 -0
- aimodelshare-0.3.62/aimodelshare/pyspark/nst.txt +213 -0
- aimodelshare-0.3.62/aimodelshare/python/my_preprocessor.py +58 -0
- aimodelshare-0.3.62/aimodelshare/readme.md +26 -0
- aimodelshare-0.3.62/aimodelshare/reproducibility.py +181 -0
- aimodelshare-0.3.62/aimodelshare/sam/Dockerfile.txt +8 -0
- aimodelshare-0.3.62/aimodelshare/sam/Dockerfile_PySpark.txt +24 -0
- aimodelshare-0.3.62/aimodelshare/sam/__init__.py +1 -0
- aimodelshare-0.3.62/aimodelshare/sam/buildspec.txt +11 -0
- aimodelshare-0.3.62/aimodelshare/sam/codebuild_policies.txt +129 -0
- aimodelshare-0.3.62/aimodelshare/sam/codebuild_trust_relationship.txt +12 -0
- aimodelshare-0.3.62/aimodelshare/sam/codepipeline_policies.txt +173 -0
- aimodelshare-0.3.62/aimodelshare/sam/codepipeline_trust_relationship.txt +12 -0
- aimodelshare-0.3.62/aimodelshare/sam/spark-class.txt +2 -0
- aimodelshare-0.3.62/aimodelshare/sam/template.txt +54 -0
- aimodelshare-0.3.62/aimodelshare/tools.py +103 -0
- aimodelshare-0.3.62/aimodelshare/utils/__init__.py +78 -0
- aimodelshare-0.3.62/aimodelshare/utils/optional_deps.py +38 -0
- aimodelshare-0.3.62/aimodelshare/utils.py +57 -0
- aimodelshare-0.3.62/aimodelshare.egg-info/PKG-INFO +298 -0
- aimodelshare-0.3.62/aimodelshare.egg-info/SOURCES.txt +368 -0
- aimodelshare-0.3.62/aimodelshare.egg-info/dependency_links.txt +1 -0
- aimodelshare-0.3.62/aimodelshare.egg-info/requires.txt +45 -0
- aimodelshare-0.3.62/aimodelshare.egg-info/top_level.txt +1 -0
- aimodelshare-0.3.62/docs/DEPRECATION_PLAN.md +89 -0
- aimodelshare-0.3.62/docs/REGION_AWARE_NAMING.md +243 -0
- aimodelshare-0.3.62/docs/aimodshare_banner.jpg +0 -0
- aimodelshare-0.3.62/docs/justice_equity_challenge_example.md +254 -0
- aimodelshare-0.3.62/infra/README.md +542 -0
- aimodelshare-0.3.62/infra/ROLLOUT_GUIDE.md +266 -0
- aimodelshare-0.3.62/infra/bootstrap/README.md +84 -0
- aimodelshare-0.3.62/infra/bootstrap/main.tf +275 -0
- aimodelshare-0.3.62/infra/bootstrap/outputs.tf +40 -0
- aimodelshare-0.3.62/infra/bootstrap/variables.tf +17 -0
- aimodelshare-0.3.62/infra/lambda/app.py +1653 -0
- aimodelshare-0.3.62/infra/lambda-layer-bucket/README.md +94 -0
- aimodelshare-0.3.62/infra/lambda-layer-bucket/main.tf +74 -0
- aimodelshare-0.3.62/infra/layer/build_layer.sh +14 -0
- aimodelshare-0.3.62/infra/layer/requirements.txt +1 -0
- aimodelshare-0.3.62/infra/main.tf +330 -0
- aimodelshare-0.3.62/infra/outputs.tf +14 -0
- aimodelshare-0.3.62/infra/terraform.tfvars +2 -0
- aimodelshare-0.3.62/infra/variables.tf +106 -0
- aimodelshare-0.3.62/launch_entrypoint.py +226 -0
- aimodelshare-0.3.62/meta.yaml +71 -0
- aimodelshare-0.3.62/minimal_session_auth_demo.py +178 -0
- aimodelshare-0.3.62/notebooks/00_Justice_Challenge_Landing.ipynb +94 -0
- aimodelshare-0.3.62/notebooks/Etica_en_Joc_Justice_Challenge (7).ipynb +423 -0
- aimodelshare-0.3.62/notebooks/Etica_en_Joc_Justice_Challenge.ipynb +627 -0
- aimodelshare-0.3.62/notebooks/Etica_en_Joc_Justice_Challenge_nightly.ipynb +585 -0
- aimodelshare-0.3.62/notebooks/aimodelshare_colab_smoke.ipynb +309 -0
- aimodelshare-0.3.62/notebooks/compas_playground_multiframework.ipynb +1344 -0
- aimodelshare-0.3.62/notebooks/moral_compass_model_submissions_and_challenge_progress.ipynb +398 -0
- aimodelshare-0.3.62/notebooks/moral_compass_playground_setup.ipynb +1 -0
- aimodelshare-0.3.62/notebooks/notebooks_compas_playground_multiframework.ipynb +919 -0
- aimodelshare-0.3.62/pyproject.toml +64 -0
- aimodelshare-0.3.62/requirements-apps.txt +27 -0
- aimodelshare-0.3.62/requirements-auth.txt +2 -0
- aimodelshare-0.3.62/requirements-eval.txt +6 -0
- aimodelshare-0.3.62/requirements.txt +31 -0
- aimodelshare-0.3.62/scripts/cache_terraform_outputs.sh +49 -0
- aimodelshare-0.3.62/scripts/cleanup_test_resources.py +532 -0
- aimodelshare-0.3.62/scripts/demo_moral_compass_metrics.py +259 -0
- aimodelshare-0.3.62/scripts/mc_rank_integration_test.py +213 -0
- aimodelshare-0.3.62/scripts/run_moral_compass_integration_test.sh +103 -0
- aimodelshare-0.3.62/scripts/verify_api_reachable.sh +80 -0
- aimodelshare-0.3.62/setup.cfg +8 -0
- aimodelshare-0.3.62/setup.py +6 -0
- aimodelshare-0.3.62/source/about.rst +18 -0
- aimodelshare-0.3.62/source/advanced_features.rst +137 -0
- aimodelshare-0.3.62/source/competition.rst +218 -0
- aimodelshare-0.3.62/source/conf.py +58 -0
- aimodelshare-0.3.62/source/create_credentials.rst +86 -0
- aimodelshare-0.3.62/source/example_notebooks.rst +132 -0
- aimodelshare-0.3.62/source/functions.rst +151 -0
- aimodelshare-0.3.62/source/gettingstarted.rst +390 -0
- aimodelshare-0.3.62/source/images/creds1.png +0 -0
- aimodelshare-0.3.62/source/images/creds2.png +0 -0
- aimodelshare-0.3.62/source/images/creds3.png +0 -0
- aimodelshare-0.3.62/source/images/creds4.png +0 -0
- aimodelshare-0.3.62/source/images/creds5.png +0 -0
- aimodelshare-0.3.62/source/images/creds_file_example.png +0 -0
- aimodelshare-0.3.62/source/images/predict_tab.png +0 -0
- aimodelshare-0.3.62/source/index.rst +110 -0
- aimodelshare-0.3.62/source/modelplayground.rst +132 -0
- aimodelshare-0.3.62/test_bias_detective_with_session.py +47 -0
- aimodelshare-0.3.62/tests/MORAL_COMPASS_INTEGRATION_TEST_README.md +238 -0
- aimodelshare-0.3.62/tests/MORAL_COMPASS_TEST_COVERAGE.md +241 -0
- aimodelshare-0.3.62/tests/QUICK_START_INTEGRATION_TEST.md +144 -0
- aimodelshare-0.3.62/tests/README.md +80 -0
- aimodelshare-0.3.62/tests/__init__.py +0 -0
- aimodelshare-0.3.62/tests/example_run_integration_test.sh +42 -0
- aimodelshare-0.3.62/tests/load_mixed_duration.py +376 -0
- aimodelshare-0.3.62/tests/load_multi_table.py +328 -0
- aimodelshare-0.3.62/tests/load_single_table.py +285 -0
- aimodelshare-0.3.62/tests/requirements.txt +3 -0
- aimodelshare-0.3.62/tests/test_aimsonnx.py +122 -0
- aimodelshare-0.3.62/tests/test_api_integration.py +421 -0
- aimodelshare-0.3.62/tests/test_api_pagination.py +213 -0
- aimodelshare-0.3.62/tests/test_bias_detective_auth.py +117 -0
- aimodelshare-0.3.62/tests/test_bias_detective_combined_score.py +180 -0
- aimodelshare-0.3.62/tests/test_bias_detective_enhancements.py +207 -0
- aimodelshare-0.3.62/tests/test_bias_detective_parts.py +54 -0
- aimodelshare-0.3.62/tests/test_bias_detective_rank_integration.py +213 -0
- aimodelshare-0.3.62/tests/test_bias_detective_task_tracking.py +250 -0
- aimodelshare-0.3.62/tests/test_bias_detective_test_mode.py +247 -0
- aimodelshare-0.3.62/tests/test_cleanup_script.py +75 -0
- aimodelshare-0.3.62/tests/test_kpi_dict_unhashable_integration.py +203 -0
- aimodelshare-0.3.62/tests/test_kpi_improvements.py +314 -0
- aimodelshare-0.3.62/tests/test_kpi_updates_on_second_submission.py +221 -0
- aimodelshare-0.3.62/tests/test_launch_entrypoint.py +135 -0
- aimodelshare-0.3.62/tests/test_model_building_game_conclusion.py +327 -0
- aimodelshare-0.3.62/tests/test_model_building_game_enhancements.py +306 -0
- aimodelshare-0.3.62/tests/test_model_building_game_readiness_gating.py +196 -0
- aimodelshare-0.3.62/tests/test_model_building_game_slider_fix.py +139 -0
- aimodelshare-0.3.62/tests/test_moral_compass_apps.py +190 -0
- aimodelshare-0.3.62/tests/test_moral_compass_auth.py +319 -0
- aimodelshare-0.3.62/tests/test_moral_compass_auth_create_table.py +165 -0
- aimodelshare-0.3.62/tests/test_moral_compass_client_minimal.py +318 -0
- aimodelshare-0.3.62/tests/test_moral_compass_comprehensive_integration.py +422 -0
- aimodelshare-0.3.62/tests/test_moral_compass_dynamic_metrics.py +415 -0
- aimodelshare-0.3.62/tests/test_moral_compass_unit.py +366 -0
- aimodelshare-0.3.62/tests/test_playground.py +721 -0
- aimodelshare-0.3.62/tests/test_playground_ai_lead_engineer_app.py +413 -0
- aimodelshare-0.3.62/tests/test_playground_compas_multiframework.py +804 -0
- aimodelshare-0.3.62/tests/test_playground_compas_multiframework_short.py +567 -0
- aimodelshare-0.3.62/tests/test_playground_keras_model_types.py +344 -0
- aimodelshare-0.3.62/tests/test_playground_model_types.py +314 -0
- aimodelshare-0.3.62/tests/test_playground_moral_compass_challenge.py +183 -0
- aimodelshare-0.3.62/tests/test_playground_torch_model_types.py +396 -0
- aimodelshare-0.3.62/tests/test_playgrounds_nodataimport.py +141 -0
- aimodelshare-0.3.62/tests/test_region_aware_naming.py +133 -0
- aimodelshare-0.3.62/tests/test_session_auto_login.py +141 -0
- aimodelshare-0.3.62/tests/test_sessionid_kpi_integration.py +215 -0
- aimodelshare-0.3.62/tests/test_submission_count_updates.py +222 -0
- aimodelshare-0.3.62/tests/test_team_assignment.py +176 -0
- aimodelshare-0.3.62/tests/test_token_authentication.py +259 -0
- aimodelshare-0.3.62/tests/unit/DEBUGGING_GUIDE.md +250 -0
- aimodelshare-0.3.62/tests/unit/README.md +204 -0
- aimodelshare-0.3.62/tests/unit/__init__.py +1 -0
- aimodelshare-0.3.62/tests/unit/run_tests.sh +74 -0
- aimodelshare-0.3.62/tests/unit/test_bucket_setup.py +161 -0
- aimodelshare-0.3.62/tests/unit/test_credentials.py +145 -0
- aimodelshare-0.3.62/tests/unit/test_data_preprocessing.py +171 -0
- aimodelshare-0.3.62/tests/unit/test_eval_metrics_smoke.py +263 -0
- aimodelshare-0.3.62/tests/unit/test_model_helpers.py +547 -0
- aimodelshare-0.3.62/tests/unit/test_model_training.py +168 -0
- aimodelshare-0.3.62/tests/unit/test_modernization.py +229 -0
- aimodelshare-0.3.62/tests/unit/test_playground_init.py +119 -0
- aimodelshare-0.3.62/tests/unit/test_playground_operations.py +198 -0
- aimodelshare-0.3.62/tests/unit/test_preprocessor_diagnostics.py +140 -0
- aimodelshare-0.3.62/tests/unit/test_preprocessor_validation.py +220 -0
- aimodelshare-0.3.62/tests/unit/test_setup_sanity.py +96 -0
- aimodelshare-0.3.62/tests/unit/test_submit_model_returns.py +130 -0
- aimodelshare-0.3.62/tests/unit/test_transformer_preprocessor.py +247 -0
- aimodelshare-0.3.62/tests/unit/test_utils_imports.py +113 -0
- aimodelshare-0.3.62/validate_modernization.py +194 -0
- aimodelshare-0.3.62/verify_enhancements.py +154 -0
- aimodelshare-0.3.62/verify_preprocessor_diagnostics.py +180 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: AI Lead Engineer App Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ai-lead-engineer-app-${{ github.ref_name }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
ai-lead-engineer-app-test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
timeout-minutes: 15
|
|
17
|
+
env:
|
|
18
|
+
TF_CPP_MIN_LOG_LEVEL: "2"
|
|
19
|
+
AIMODELSHARE_SUPPRESS_OPTIONAL_WARNINGS: "1"
|
|
20
|
+
CUDA_VISIBLE_DEVICES: "-1" # Force CPU-only for TensorFlow
|
|
21
|
+
# Safely expose secrets as env (empty if unavailable, e.g., fork PRs)
|
|
22
|
+
AIMODELSHARE_USERNAME: ${{ secrets.AIMODELSHARE_USERNAME }}
|
|
23
|
+
AIMODELSHARE_PASSWORD: ${{ secrets.AIMODELSHARE_PASSWORD }}
|
|
24
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
25
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
26
|
+
AWS_REGION: ${{ secrets.AWS_REGION }}
|
|
27
|
+
|
|
28
|
+
strategy:
|
|
29
|
+
matrix:
|
|
30
|
+
python-version: ["3.11"]
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout code
|
|
34
|
+
uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
37
|
+
uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: ${{ matrix.python-version }}
|
|
40
|
+
cache: "pip"
|
|
41
|
+
|
|
42
|
+
- name: Upgrade pip
|
|
43
|
+
run: |
|
|
44
|
+
python -m pip install --upgrade pip
|
|
45
|
+
|
|
46
|
+
- name: Install dependencies
|
|
47
|
+
run: |
|
|
48
|
+
# Core dependencies
|
|
49
|
+
pip install boto3 onnx onnxmltools onnxruntime Pympler scikeras shortuuid skl2onnx tf2onnx wget
|
|
50
|
+
# Package in editable mode
|
|
51
|
+
pip install -e .
|
|
52
|
+
# Test and ML dependencies
|
|
53
|
+
pip install pytest scikit-learn pandas numpy opencv-python-headless pydot regex psutil IPython matplotlib seaborn importlib_resources onnxscript
|
|
54
|
+
# TensorFlow (CPU-only)
|
|
55
|
+
pip install tensorflow-cpu
|
|
56
|
+
# PyTorch (CPU-only)
|
|
57
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch torchvision
|
|
58
|
+
# Gradio UI
|
|
59
|
+
pip install gradio
|
|
60
|
+
|
|
61
|
+
- name: Verify CPU-only TensorFlow
|
|
62
|
+
run: |
|
|
63
|
+
python -c "import tensorflow as tf, os; os.environ['CUDA_VISIBLE_DEVICES']='-1'; print('TensorFlow GPUs:', len(tf.config.list_physical_devices('GPU'))); print('CPU-only mode verified');"
|
|
64
|
+
|
|
65
|
+
- name: Set up test environment (if credentials available)
|
|
66
|
+
if: ${{ env.AIMODELSHARE_USERNAME != '' && env.AIMODELSHARE_PASSWORD != '' }}
|
|
67
|
+
run: |
|
|
68
|
+
echo "username=${AIMODELSHARE_USERNAME}" >> "$GITHUB_ENV"
|
|
69
|
+
echo "password=${AIMODELSHARE_PASSWORD}" >> "$GITHUB_ENV"
|
|
70
|
+
echo "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" >> "$GITHUB_ENV"
|
|
71
|
+
echo "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" >> "$GITHUB_ENV"
|
|
72
|
+
echo "AWS_REGION=${AWS_REGION}" >> "$GITHUB_ENV"
|
|
73
|
+
|
|
74
|
+
- name: Run AI Lead Engineer app tests
|
|
75
|
+
run: |
|
|
76
|
+
pytest tests/test_playground_ai_lead_engineer_app.py -v -s --tb=short
|
|
77
|
+
|
|
78
|
+
- name: Test app import from moral_compass module
|
|
79
|
+
run: |
|
|
80
|
+
python - <<'PY'
|
|
81
|
+
from aimodelshare.moral_compass import create_ai_lead_engineer_app, launch_ai_lead_engineer_app
|
|
82
|
+
print('✓ Import from moral_compass module successful')
|
|
83
|
+
|
|
84
|
+
from aimodelshare.moral_compass.apps import create_ai_lead_engineer_app as create2, launch_ai_lead_engineer_app as launch2
|
|
85
|
+
print('✓ Import from apps module successful')
|
|
86
|
+
|
|
87
|
+
app = create_ai_lead_engineer_app()
|
|
88
|
+
assert app is not None
|
|
89
|
+
print('✓ App instantiation successful')
|
|
90
|
+
PY
|
|
91
|
+
|
|
92
|
+
- name: Summary
|
|
93
|
+
if: always()
|
|
94
|
+
run: |
|
|
95
|
+
echo "AI Lead Engineer App Test Summary"
|
|
96
|
+
echo "=================================="
|
|
97
|
+
echo "Python version: ${{ matrix.python-version }}"
|
|
98
|
+
echo "Status: Test completed"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: Test latest master branch aimodelshare
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch: # Manual trigger only
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: master-aimodelshare-tests
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
run-tests:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
timeout-minutes: 120
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
USERNAME: ${{ secrets.AIMODELSHARE_USERNAME }}
|
|
20
|
+
PASSWORD: ${{ secrets.AIMODELSHARE_PASSWORD }}
|
|
21
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.DATA_AWS_ACCESS_KEY_ID }}
|
|
22
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.DATA_AWS_SECRET_ACCESS_KEY }}
|
|
23
|
+
AWS_REGION: us-east-1
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout repository (master)
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
# Uncomment the next line if you want to ALWAYS test master even when dispatching from another ref
|
|
30
|
+
# ref: master
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Show commit being tested
|
|
34
|
+
run: |
|
|
35
|
+
echo "Testing commit:"
|
|
36
|
+
git --no-pager log -1 --oneline
|
|
37
|
+
echo "Current branch (if detached this may be a commit SHA):"
|
|
38
|
+
git branch --show-current || true
|
|
39
|
+
|
|
40
|
+
- name: Set up Python
|
|
41
|
+
uses: actions/setup-python@v5
|
|
42
|
+
with:
|
|
43
|
+
python-version: "3.10"
|
|
44
|
+
cache: "pip"
|
|
45
|
+
|
|
46
|
+
- name: Upgrade pip
|
|
47
|
+
run: |
|
|
48
|
+
python -m pip install --upgrade pip
|
|
49
|
+
|
|
50
|
+
- name: Install local aimodelshare (editable) + test dependencies
|
|
51
|
+
run: |
|
|
52
|
+
pip install boto3 onnx onnxmltools onnxruntime Pympler scikeras shortuuid skl2onnx tf2onnx wget
|
|
53
|
+
pip install -e .
|
|
54
|
+
pip install pytest scikit-learn pandas numpy opencv-python-headless tensorflow pydot regex psutil IPython "PyJWT<2.0" matplotlib seaborn importlib_resources onnxscript
|
|
55
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch torchvision
|
|
56
|
+
python -c "import aimodelshare, os; print('aimodelshare imported from:', aimodelshare.__file__)"
|
|
57
|
+
|
|
58
|
+
- name: Verify import now points to repository source (not PyPI)
|
|
59
|
+
run: |
|
|
60
|
+
python - <<'PYCODE'
|
|
61
|
+
import aimodelshare, os
|
|
62
|
+
path = aimodelshare.__file__
|
|
63
|
+
print("Resolved aimodelshare.__file__:", path)
|
|
64
|
+
repo_root = os.getcwd()
|
|
65
|
+
assert repo_root in os.path.abspath(path), f"aimodelshare does not appear to come from the checked-out repository root: {repo_root}"
|
|
66
|
+
assert "site-packages" not in path, "aimodelshare should NOT be the PyPI site-packages build."
|
|
67
|
+
print("Verification passed: using local master branch source.")
|
|
68
|
+
PYCODE
|
|
69
|
+
|
|
70
|
+
- name: Run targeted tests against local master branch
|
|
71
|
+
run: |
|
|
72
|
+
echo "Starting pytest for tests/test_playgrounds_nodataimport.py"
|
|
73
|
+
pytest -vv tests/test_aimsonnx.py
|
|
74
|
+
pytest -vv tests/test_playgrounds_nodataimport.py
|
|
75
|
+
|
|
76
|
+
- name: Post-run diagnostics (always runs)
|
|
77
|
+
if: always()
|
|
78
|
+
run: |
|
|
79
|
+
echo "Job conclusion: ${{ job.status }}"
|
|
80
|
+
python - <<'PYCODE'
|
|
81
|
+
import aimodelshare
|
|
82
|
+
print("aimodelshare version attribute (may reflect local dev state):", getattr(aimodelshare, "__version__", "unknown"))
|
|
83
|
+
print("Module file path:", aimodelshare.__file__)
|
|
84
|
+
PYCODE
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
name: Bootstrap Terraform State Resources
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
workflow_call:
|
|
6
|
+
outputs:
|
|
7
|
+
s3_bucket_name:
|
|
8
|
+
description: "Name of the created S3 bucket"
|
|
9
|
+
value: ${{ jobs.bootstrap.outputs.s3_bucket_name }}
|
|
10
|
+
dynamodb_table_name:
|
|
11
|
+
description: "Name of the created DynamoDB table"
|
|
12
|
+
value: ${{ jobs.bootstrap.outputs.dynamodb_table_name }}
|
|
13
|
+
github_actions_role_arn:
|
|
14
|
+
description: "ARN of the created GitHub Actions IAM role"
|
|
15
|
+
value: ${{ jobs.bootstrap.outputs.github_actions_role_arn }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
bootstrap:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
outputs:
|
|
22
|
+
s3_bucket_name: ${{ steps.terraform_output.outputs.s3_bucket_name }}
|
|
23
|
+
dynamodb_table_name: ${{ steps.terraform_output.outputs.dynamodb_table_name }}
|
|
24
|
+
github_actions_role_arn: ${{ steps.terraform_output.outputs.github_actions_role_arn }}
|
|
25
|
+
|
|
26
|
+
permissions:
|
|
27
|
+
contents: read
|
|
28
|
+
|
|
29
|
+
env:
|
|
30
|
+
AWS_REGION: ${{ vars.AWS_REGION || 'us-east-1' }}
|
|
31
|
+
TF_IN_AUTOMATION: "true"
|
|
32
|
+
|
|
33
|
+
steps:
|
|
34
|
+
- name: Checkout
|
|
35
|
+
uses: actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
- name: Setup Terraform
|
|
38
|
+
uses: hashicorp/setup-terraform@v3
|
|
39
|
+
with:
|
|
40
|
+
terraform_version: 1.9.5
|
|
41
|
+
terraform_wrapper: false
|
|
42
|
+
|
|
43
|
+
# Configure AWS credentials using access keys per company policy
|
|
44
|
+
# Note: Requires AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY repository secrets
|
|
45
|
+
# Security: Ensure access keys follow principle of least privilege and key rotation policies
|
|
46
|
+
- name: Configure AWS credentials
|
|
47
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
48
|
+
with:
|
|
49
|
+
aws-access-key-id: ${{ secrets.DATA_AWS_ACCESS_KEY_ID }}
|
|
50
|
+
aws-secret-access-key: ${{ secrets.DATA_AWS_SECRET_ACCESS_KEY }}
|
|
51
|
+
aws-region: ${{ env.AWS_REGION }}
|
|
52
|
+
|
|
53
|
+
- name: Check if resources already exist
|
|
54
|
+
id: check_resources
|
|
55
|
+
working-directory: infra/bootstrap
|
|
56
|
+
run: |
|
|
57
|
+
# Check if S3 bucket exists
|
|
58
|
+
if aws s3api head-bucket --bucket "aimodelshare-tfstate-prod-copilot-2024" 2>/dev/null; then
|
|
59
|
+
echo "s3_exists=true" >> $GITHUB_OUTPUT
|
|
60
|
+
else
|
|
61
|
+
echo "s3_exists=false" >> $GITHUB_OUTPUT
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# Check if DynamoDB table exists
|
|
65
|
+
if aws dynamodb describe-table --table-name "aimodelshare-tf-locks" 2>/dev/null; then
|
|
66
|
+
echo "dynamodb_exists=true" >> $GITHUB_OUTPUT
|
|
67
|
+
else
|
|
68
|
+
echo "dynamodb_exists=false" >> $GITHUB_OUTPUT
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Check if GitHub OIDC provider exists
|
|
72
|
+
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
|
73
|
+
if aws iam get-open-id-connect-provider --open-id-connect-provider-arn "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com" 2>/dev/null; then
|
|
74
|
+
echo "oidc_provider_exists=true" >> $GITHUB_OUTPUT
|
|
75
|
+
else
|
|
76
|
+
echo "oidc_provider_exists=false" >> $GITHUB_OUTPUT
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Check if GitHub Actions IAM role exists
|
|
80
|
+
if aws iam get-role --role-name "aimodelshare-github-oidc-deployer" 2>/dev/null; then
|
|
81
|
+
echo "github_role_exists=true" >> $GITHUB_OUTPUT
|
|
82
|
+
else
|
|
83
|
+
echo "github_role_exists=false" >> $GITHUB_OUTPUT
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
- name: Terraform Init
|
|
87
|
+
working-directory: infra/bootstrap
|
|
88
|
+
run: terraform init -input=false
|
|
89
|
+
|
|
90
|
+
- name: Terraform Validate
|
|
91
|
+
working-directory: infra/bootstrap
|
|
92
|
+
run: terraform validate
|
|
93
|
+
|
|
94
|
+
- name: Import existing resources (if they exist)
|
|
95
|
+
working-directory: infra/bootstrap
|
|
96
|
+
if: steps.check_resources.outputs.s3_exists == 'true' || steps.check_resources.outputs.dynamodb_exists == 'true' || steps.check_resources.outputs.oidc_provider_exists == 'true' || steps.check_resources.outputs.github_role_exists == 'true'
|
|
97
|
+
run: |
|
|
98
|
+
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
|
99
|
+
|
|
100
|
+
if [ "${{ steps.check_resources.outputs.s3_exists }}" = "true" ]; then
|
|
101
|
+
echo "Importing existing S3 bucket..."
|
|
102
|
+
terraform import aws_s3_bucket.terraform_state aimodelshare-tfstate-prod-copilot-2024 || true
|
|
103
|
+
terraform import aws_s3_bucket_versioning.terraform_state aimodelshare-tfstate-prod-copilot-2024 || true
|
|
104
|
+
terraform import aws_s3_bucket_server_side_encryption_configuration.terraform_state aimodelshare-tfstate-prod-copilot-2024 || true
|
|
105
|
+
terraform import aws_s3_bucket_public_access_block.terraform_state aimodelshare-tfstate-prod-copilot-2024 || true
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if [ "${{ steps.check_resources.outputs.dynamodb_exists }}" = "true" ]; then
|
|
109
|
+
echo "Importing existing DynamoDB table..."
|
|
110
|
+
terraform import aws_dynamodb_table.terraform_locks aimodelshare-tf-locks || true
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
if [ "${{ steps.check_resources.outputs.oidc_provider_exists }}" = "true" ]; then
|
|
114
|
+
echo "Importing existing GitHub OIDC provider..."
|
|
115
|
+
terraform import aws_iam_openid_connect_provider.github "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com" || true
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if [ "${{ steps.check_resources.outputs.github_role_exists }}" = "true" ]; then
|
|
119
|
+
echo "Importing existing GitHub Actions IAM role..."
|
|
120
|
+
terraform import aws_iam_role.github_actions aimodelshare-github-oidc-deployer || true
|
|
121
|
+
# Also try to import the policy and attachment if they exist
|
|
122
|
+
terraform import aws_iam_policy.github_actions_deployment "arn:aws:iam::${ACCOUNT_ID}:policy/aimodelshare-github-actions-deployment" || true
|
|
123
|
+
terraform import aws_iam_role_policy_attachment.github_actions_deployment aimodelshare-github-oidc-deployer/arn:aws:iam::${ACCOUNT_ID}:policy/aimodelshare-github-actions-deployment || true
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
- name: Terraform Plan
|
|
127
|
+
id: plan
|
|
128
|
+
working-directory: infra/bootstrap
|
|
129
|
+
run: |
|
|
130
|
+
terraform plan -input=false -out=tfplan
|
|
131
|
+
|
|
132
|
+
- name: Terraform Apply
|
|
133
|
+
working-directory: infra/bootstrap
|
|
134
|
+
run: terraform apply -input=false -auto-approve tfplan
|
|
135
|
+
|
|
136
|
+
- name: Get Terraform Outputs
|
|
137
|
+
id: terraform_output
|
|
138
|
+
working-directory: infra/bootstrap
|
|
139
|
+
run: |
|
|
140
|
+
S3_BUCKET=$(terraform output -raw s3_bucket_name)
|
|
141
|
+
DYNAMODB_TABLE=$(terraform output -raw dynamodb_table_name)
|
|
142
|
+
GITHUB_ROLE_ARN=$(terraform output -raw github_actions_role_arn)
|
|
143
|
+
echo "s3_bucket_name=$S3_BUCKET" >> $GITHUB_OUTPUT
|
|
144
|
+
echo "dynamodb_table_name=$DYNAMODB_TABLE" >> $GITHUB_OUTPUT
|
|
145
|
+
echo "github_actions_role_arn=$GITHUB_ROLE_ARN" >> $GITHUB_OUTPUT
|
|
146
|
+
echo "✅ Bootstrap completed successfully!"
|
|
147
|
+
echo " S3 Bucket: $S3_BUCKET"
|
|
148
|
+
echo " DynamoDB Table: $DYNAMODB_TABLE"
|
|
149
|
+
echo " GitHub Actions Role ARN: $GITHUB_ROLE_ARN"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: Cleanup Test Resources
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
mode:
|
|
7
|
+
description: 'Mode of operation'
|
|
8
|
+
required: true
|
|
9
|
+
default: 'dry-run'
|
|
10
|
+
type: choice
|
|
11
|
+
options:
|
|
12
|
+
- dry-run # list only
|
|
13
|
+
- plan # list with optional filters
|
|
14
|
+
- delete # delete specified resources
|
|
15
|
+
region:
|
|
16
|
+
description: 'AWS region'
|
|
17
|
+
required: false
|
|
18
|
+
default: 'us-east-1'
|
|
19
|
+
user_filter:
|
|
20
|
+
description: 'Substring filter for IAM usernames (plan/dry-run modes)'
|
|
21
|
+
required: false
|
|
22
|
+
playground_ids:
|
|
23
|
+
description: 'Comma-separated API Gateway REST API IDs to delete (delete mode)'
|
|
24
|
+
required: false
|
|
25
|
+
iam_usernames:
|
|
26
|
+
description: 'Comma-separated IAM usernames to delete (delete mode)'
|
|
27
|
+
required: false
|
|
28
|
+
confirm:
|
|
29
|
+
description: "Type DELETE to allow deletions (required for delete mode)"
|
|
30
|
+
required: false
|
|
31
|
+
|
|
32
|
+
permissions:
|
|
33
|
+
contents: read
|
|
34
|
+
# If you later move to OIDC role assumption, uncomment:
|
|
35
|
+
# id-token: write
|
|
36
|
+
|
|
37
|
+
jobs:
|
|
38
|
+
cleanup:
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
timeout-minutes: 30
|
|
41
|
+
|
|
42
|
+
env:
|
|
43
|
+
AWS_REGION: ${{ github.event.inputs.region || 'us-east-1' }}
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- name: Checkout repository
|
|
47
|
+
uses: actions/checkout@v4
|
|
48
|
+
|
|
49
|
+
- name: Set up Python
|
|
50
|
+
uses: actions/setup-python@v5
|
|
51
|
+
with:
|
|
52
|
+
python-version: "3.10"
|
|
53
|
+
|
|
54
|
+
# Configure AWS credentials (currently using static secrets; consider switching to OIDC)
|
|
55
|
+
- name: Configure AWS credentials
|
|
56
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
57
|
+
with:
|
|
58
|
+
aws-access-key-id: ${{ secrets.DATA_AWS_ACCESS_KEY_ID }}
|
|
59
|
+
aws-secret-access-key: ${{ secrets.DATA_AWS_SECRET_ACCESS_KEY }}
|
|
60
|
+
aws-region: ${{ env.AWS_REGION }}
|
|
61
|
+
|
|
62
|
+
- name: Install dependencies
|
|
63
|
+
run: |
|
|
64
|
+
pip install boto3
|
|
65
|
+
|
|
66
|
+
- name: List resources (dry-run / plan modes)
|
|
67
|
+
if: ${{ github.event.inputs.mode == 'dry-run' || github.event.inputs.mode == 'plan' }}
|
|
68
|
+
run: |
|
|
69
|
+
echo "Listing resources (mode=${{ github.event.inputs.mode }})"
|
|
70
|
+
python scripts/cleanup_test_resources.py --region ${{ env.AWS_REGION }} --list-only $([ -n "${{ github.event.inputs.user_filter }}" ] && echo "--user-filter '${{ github.event.inputs.user_filter }}'")
|
|
71
|
+
shell: bash
|
|
72
|
+
|
|
73
|
+
- name: Validate delete inputs
|
|
74
|
+
if: ${{ github.event.inputs.mode == 'delete' }}
|
|
75
|
+
run: |
|
|
76
|
+
echo "Validating delete inputs..."
|
|
77
|
+
if [ "${{ github.event.inputs.confirm }}" != "DELETE" ]; then
|
|
78
|
+
echo "Deletion not confirmed. 'confirm' must be DELETE."; exit 1;
|
|
79
|
+
fi
|
|
80
|
+
if [ -z "${{ github.event.inputs.playground_ids }}" ] && [ -z "${{ github.event.inputs.iam_usernames }}" ]; then
|
|
81
|
+
echo "Nothing to delete. Provide playground_ids and/or iam_usernames."; exit 1;
|
|
82
|
+
fi
|
|
83
|
+
shell: bash
|
|
84
|
+
|
|
85
|
+
- name: Perform deletion
|
|
86
|
+
if: ${{ github.event.inputs.mode == 'delete' }}
|
|
87
|
+
run: |
|
|
88
|
+
echo "Starting deletion..."
|
|
89
|
+
python scripts/cleanup_test_resources.py \
|
|
90
|
+
--region ${{ env.AWS_REGION }} \
|
|
91
|
+
--playgrounds "${{ github.event.inputs.playground_ids }}" \
|
|
92
|
+
--users "${{ github.event.inputs.iam_usernames }}" \
|
|
93
|
+
--confirm-delete DELETE
|
|
94
|
+
shell: bash
|
|
95
|
+
|
|
96
|
+
- name: Summary
|
|
97
|
+
if: always()
|
|
98
|
+
run: |
|
|
99
|
+
echo "Cleanup workflow completed"
|
|
100
|
+
echo "Mode: ${{ github.event.inputs.mode }}"
|
|
101
|
+
echo "Region: ${{ env.AWS_REGION }}"
|
|
102
|
+
echo "User filter: ${{ github.event.inputs.user_filter }}"
|
|
103
|
+
echo "Playground IDs: ${{ github.event.inputs.playground_ids }}"
|
|
104
|
+
echo "IAM Usernames: ${{ github.event.inputs.iam_usernames }}"
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
name: Deploy Infra (Terraform Workspaces)
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
bootstrap:
|
|
8
|
+
uses: ./.github/workflows/bootstrap-terraform.yml
|
|
9
|
+
secrets: inherit
|
|
10
|
+
|
|
11
|
+
deploy:
|
|
12
|
+
needs: bootstrap
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
env: [dev]
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
env:
|
|
23
|
+
AWS_REGION: ${{ vars.AWS_REGION || 'us-east-1' }}
|
|
24
|
+
TF_IN_AUTOMATION: "true"
|
|
25
|
+
username: ${{ secrets.AIMODELSHARE_USERNAME }}
|
|
26
|
+
password: ${{ secrets.AIMODELSHARE_PASSWORD }}
|
|
27
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.DATA_AWS_ACCESS_KEY_ID }}
|
|
28
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.DATA_AWS_SECRET_ACCESS_KEY }}
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout
|
|
32
|
+
uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Setup Terraform
|
|
35
|
+
uses: hashicorp/setup-terraform@v3
|
|
36
|
+
with:
|
|
37
|
+
terraform_version: 1.9.5
|
|
38
|
+
|
|
39
|
+
- name: Configure AWS credentials
|
|
40
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
41
|
+
with:
|
|
42
|
+
aws-access-key-id: ${{ secrets.DATA_AWS_ACCESS_KEY_ID }}
|
|
43
|
+
aws-secret-access-key: ${{ secrets.DATA_AWS_SECRET_ACCESS_KEY }}
|
|
44
|
+
aws-region: ${{ env.AWS_REGION }}
|
|
45
|
+
|
|
46
|
+
- name: (Optional) Build Lambda Layer
|
|
47
|
+
working-directory: infra/layer
|
|
48
|
+
run: |
|
|
49
|
+
if [ -f requirements.txt ]; then
|
|
50
|
+
bash build_layer.sh || true
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
- name: Terraform Init
|
|
54
|
+
working-directory: infra
|
|
55
|
+
run: terraform init -input=false
|
|
56
|
+
|
|
57
|
+
- name: Select/Create Workspace
|
|
58
|
+
working-directory: infra
|
|
59
|
+
run: |
|
|
60
|
+
set -euo pipefail
|
|
61
|
+
|
|
62
|
+
WS="${{ matrix.env }}"
|
|
63
|
+
echo "Ensuring Terraform workspace '${WS}' exists..."
|
|
64
|
+
if terraform workspace list | sed 's/^[* ]*//' | grep -Fxq "$WS"; then
|
|
65
|
+
echo "Selecting existing workspace: $WS"
|
|
66
|
+
terraform workspace select "$WS"
|
|
67
|
+
else
|
|
68
|
+
echo "Creating new workspace: $WS"
|
|
69
|
+
terraform workspace new "$WS"
|
|
70
|
+
fi
|
|
71
|
+
echo "Current workspace: $(terraform workspace show)"
|
|
72
|
+
|
|
73
|
+
if [ ! -d .terraform ]; then
|
|
74
|
+
echo "Terraform not initialized yet; running 'terraform init'..."
|
|
75
|
+
terraform init -input=false
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
STATE_KEY="env:/${WS}/aimodelshare/infra/terraform.tfstate"
|
|
79
|
+
echo "Checking if remote state object exists: ${STATE_KEY}"
|
|
80
|
+
if aws s3api head-object --bucket "aimodelshare-tfstate-prod-copilot-2024" --key "${STATE_KEY}" >/dev/null 2>&1; then
|
|
81
|
+
echo "Remote state object exists for workspace '${WS}'"
|
|
82
|
+
else
|
|
83
|
+
echo "Remote state object missing for workspace '${WS}' - creating initial state"
|
|
84
|
+
terraform apply -auto-approve -target=null_resource.state_seed
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo "Workspace '$WS' ready; proceeding to plan/apply steps."
|
|
88
|
+
|
|
89
|
+
- name: Terraform Validate
|
|
90
|
+
working-directory: infra
|
|
91
|
+
run: terraform validate
|
|
92
|
+
|
|
93
|
+
- name: Terraform Plan
|
|
94
|
+
id: plan
|
|
95
|
+
working-directory: infra
|
|
96
|
+
run: terraform plan -input=false -out=tfplan
|
|
97
|
+
|
|
98
|
+
- name: Terraform Apply
|
|
99
|
+
if: github.ref == 'refs/heads/master'
|
|
100
|
+
working-directory: infra
|
|
101
|
+
run: terraform apply -input=false -auto-approve tfplan
|
|
102
|
+
|
|
103
|
+
- name: Show Outputs
|
|
104
|
+
working-directory: infra
|
|
105
|
+
run: terraform output -json
|
|
106
|
+
|
|
107
|
+
- name: Wait for DynamoDB GSI readiness
|
|
108
|
+
if: github.ref == 'refs/heads/master'
|
|
109
|
+
working-directory: infra
|
|
110
|
+
run: |
|
|
111
|
+
TABLE_NAME=$(terraform output -raw dynamodb_table_name)
|
|
112
|
+
echo "Waiting for GSI 'byUser' on table $TABLE_NAME to become ACTIVE..."
|
|
113
|
+
ATTEMPTS=0
|
|
114
|
+
MAX_ATTEMPTS=30
|
|
115
|
+
SLEEP_SECONDS=5
|
|
116
|
+
while true; do
|
|
117
|
+
STATUS=$(aws dynamodb describe-table --table-name "$TABLE_NAME" \
|
|
118
|
+
--query "Table.GlobalSecondaryIndexes[?IndexName=='byUser'].IndexStatus" --output text 2>/dev/null || echo "UNKNOWN")
|
|
119
|
+
if [ "$STATUS" = "ACTIVE" ]; then
|
|
120
|
+
echo "GSI 'byUser' is ACTIVE."
|
|
121
|
+
break
|
|
122
|
+
fi
|
|
123
|
+
ATTEMPTS=$((ATTEMPTS+1))
|
|
124
|
+
if [ $ATTEMPTS -ge $MAX_ATTEMPTS ]; then
|
|
125
|
+
echo "Timeout waiting for GSI 'byUser' to become ACTIVE (last status: $STATUS)"
|
|
126
|
+
exit 1
|
|
127
|
+
fi
|
|
128
|
+
echo "Attempt $ATTEMPTS/$MAX_ATTEMPTS: status=$STATUS; sleeping $SLEEP_SECONDS s..."
|
|
129
|
+
sleep $SLEEP_SECONDS
|
|
130
|
+
done
|
|
131
|
+
|
|
132
|
+
- name: Cache Terraform Outputs
|
|
133
|
+
if: github.ref == 'refs/heads/master'
|
|
134
|
+
working-directory: .
|
|
135
|
+
run: |
|
|
136
|
+
bash scripts/cache_terraform_outputs.sh
|
|
137
|
+
|
|
138
|
+
- name: Verify API Health Endpoint
|
|
139
|
+
if: github.ref == 'refs/heads/master'
|
|
140
|
+
working-directory: .
|
|
141
|
+
run: |
|
|
142
|
+
bash scripts/verify_api_reachable.sh
|
|
143
|
+
|
|
144
|
+
- name: Install Package in Editable Mode
|
|
145
|
+
if: github.ref == 'refs/heads/master'
|
|
146
|
+
working-directory: .
|
|
147
|
+
run: |
|
|
148
|
+
python -m pip install --upgrade pip
|
|
149
|
+
python -m pip install -e .
|
|
150
|
+
|
|
151
|
+
- name: Run moral_compass Integration Tests
|
|
152
|
+
if: github.ref == 'refs/heads/master'
|
|
153
|
+
working-directory: .
|
|
154
|
+
run: |
|
|
155
|
+
python -m pip install pytest
|
|
156
|
+
pytest -m test_moral_compass_client_auth.py -v
|
|
157
|
+
|
|
158
|
+
- name: Run API Integration Tests
|
|
159
|
+
if: github.ref == 'refs/heads/master'
|
|
160
|
+
working-directory: .
|
|
161
|
+
run: |
|
|
162
|
+
API_BASE_URL=$(cd infra && terraform output -raw api_base_url)
|
|
163
|
+
echo "API Base URL: $API_BASE_URL"
|
|
164
|
+
|
|
165
|
+
if [[ -z "$API_BASE_URL" || "$API_BASE_URL" == "null" ]]; then
|
|
166
|
+
echo "❌ Failed to get API base URL from Terraform outputs"
|
|
167
|
+
exit 1
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
python -m pip install --upgrade pip
|
|
171
|
+
python -m pip install requests
|
|
172
|
+
|
|
173
|
+
echo "⏳ Extra stabilization wait (30s) after GSI readiness..."
|
|
174
|
+
sleep 30
|
|
175
|
+
|
|
176
|
+
echo "🚀 Starting API Integration Tests..."
|
|
177
|
+
python tests/test_api_integration.py "$API_BASE_URL"
|
|
178
|
+
|
|
179
|
+
- name: Run Pagination Tests
|
|
180
|
+
if: github.ref == 'refs/heads/master'
|
|
181
|
+
working-directory: .
|
|
182
|
+
run: |
|
|
183
|
+
API_BASE_URL=$(cd infra && terraform output -raw api_base_url)
|
|
184
|
+
echo "API Base URL: $API_BASE_URL"
|
|
185
|
+
python -m pip install requests
|
|
186
|
+
python tests/test_api_pagination.py "$API_BASE_URL"
|
|
187
|
+
|
|
188
|
+
- name: Install Load Test Dependencies
|
|
189
|
+
if: github.ref == 'refs/heads/master' && (vars.RUN_LOAD_TESTS != 'false')
|
|
190
|
+
working-directory: .
|
|
191
|
+
run: |
|
|
192
|
+
python -m pip install aiohttp rich
|
|
193
|
+
|
|
194
|
+
- name: Run Load Tests - Single Table
|
|
195
|
+
if: github.ref == 'refs/heads/master' && (vars.RUN_LOAD_TESTS != 'false')
|
|
196
|
+
working-directory: .
|
|
197
|
+
run: |
|
|
198
|
+
API_BASE_URL=$(cd infra && terraform output -raw api_base_url)
|
|
199
|
+
export API_BASE_URL
|
|
200
|
+
echo "🚀 Running Single Table Load Test..."
|
|
201
|
+
python tests/load_single_table.py
|
|
202
|
+
|
|
203
|
+
- name: Run Load Tests - Multi Table
|
|
204
|
+
if: github.ref == 'refs/heads/master' && (vars.RUN_LOAD_TESTS != 'false')
|
|
205
|
+
working-directory: .
|
|
206
|
+
run: |
|
|
207
|
+
API_BASE_URL=$(cd infra && terraform output -raw api_base_url)
|
|
208
|
+
export API_BASE_URL
|
|
209
|
+
echo "🚀 Running Multi Table Load Test..."
|
|
210
|
+
python tests/load_multi_table.py
|
|
211
|
+
|
|
212
|
+
- name: Run Load Tests - Mixed Duration
|
|
213
|
+
if: github.ref == 'refs/heads/master' && (vars.RUN_LOAD_TESTS != 'false')
|
|
214
|
+
working-directory: .
|
|
215
|
+
env:
|
|
216
|
+
LOAD_DURATION_SECONDS: 20
|
|
217
|
+
run: |
|
|
218
|
+
API_BASE_URL=$(cd infra && terraform output -raw api_base_url)
|
|
219
|
+
export API_BASE_URL
|
|
220
|
+
echo "🚀 Running Mixed Duration Load Test (20s for CI)..."
|
|
221
|
+
python tests/load_mixed_duration.py
|