squidient 3.0.4__tar.gz → 3.0.7__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.
Files changed (174) hide show
  1. {squidient-3.0.4 → squidient-3.0.7}/PKG-INFO +1 -1
  2. {squidient-3.0.4 → squidient-3.0.7}/pyproject.toml +1 -1
  3. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/cli/monitoring.py +1 -1
  4. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/cli/staging.py +1 -1
  5. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/configure.py +35 -3
  6. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/btest.html +5 -1
  7. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/test.html +5 -1
  8. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/monitoring/monitoring.py +1 -3
  9. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/staging/staging.py +4 -4
  10. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/benchmarks/failure_notifier.py +17 -1
  11. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/cases/instance.py +18 -5
  12. {squidient-3.0.4 → squidient-3.0.7}/.gitignore +0 -0
  13. {squidient-3.0.4 → squidient-3.0.7}/LICENSE.txt +0 -0
  14. {squidient-3.0.4 → squidient-3.0.7}/README.md +0 -0
  15. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/__init__.py +0 -0
  16. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/builds/benchmark_build_execution.py +0 -0
  17. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/builds/benchmark_build_orchestrator.py +0 -0
  18. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/builds/build_definition.py +0 -0
  19. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/builds/build_execution.py +0 -0
  20. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/builds/build_orchestrator.py +0 -0
  21. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/builds/build_presets.py +0 -0
  22. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/cli/__init__.py +0 -0
  23. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/cli/__main__.py +0 -0
  24. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/cli/main.py +0 -0
  25. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/code_coverage/code_coverage.py +0 -0
  26. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/code_coverage/gcovr_code_coverage.py +0 -0
  27. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/code_coverage/intel_code_coverage.py +0 -0
  28. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/compare.py +0 -0
  29. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/compare_with_diff_table.py +0 -0
  30. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/absolute.py +0 -0
  31. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/close.py +0 -0
  32. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/diff.py +0 -0
  33. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/l1_norm.py +0 -0
  34. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/l1_relative.py +0 -0
  35. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/l2_norm.py +0 -0
  36. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/l2_relative.py +0 -0
  37. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/linf_norm.py +0 -0
  38. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/linf_relative.py +0 -0
  39. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/power.py +0 -0
  40. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/relative.py +0 -0
  41. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/scalar_tolerance.py +0 -0
  42. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/tolerance.py +0 -0
  43. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compare/methods/vector_tolerance.py +0 -0
  44. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/compilation/cmake_options.py +0 -0
  45. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/configuration/__init__.py +0 -0
  46. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/configuration/generator.py +0 -0
  47. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/configuration/prompts.py +0 -0
  48. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/connection/job.py +0 -0
  49. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/connection/ssh.py +0 -0
  50. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/connection/ssh_config_checker.py +0 -0
  51. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/.squidient-initialized +0 -0
  52. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-alamak.json +0 -0
  53. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-chemint.json +0 -0
  54. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-clang.json +0 -0
  55. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-commdom.json +0 -0
  56. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-gnu.json +0 -0
  57. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-intel.json +0 -0
  58. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-mumps.json +0 -0
  59. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-nvhpc.json +0 -0
  60. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/alya-config/cmake-talp.json +0 -0
  61. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/benchmarks/benchmarks.json +0 -0
  62. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/builds/builds.json +0 -0
  63. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/builds/cc.json +0 -0
  64. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/builds/defaults.json +0 -0
  65. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/builds/predefined-old.json +0 -0
  66. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/builds/predefined.json +0 -0
  67. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/configurations/projects.json +0 -0
  68. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/configurations/systems.json +0 -0
  69. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/configurations/tests.json +0 -0
  70. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/email/report.html +0 -0
  71. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/icons/big.png +0 -0
  72. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/icons/small.png +0 -0
  73. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/index.html +0 -0
  74. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/.gitignore +0 -0
  75. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small/.gitignore +0 -0
  76. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small/t3.small/cloud-init-slurm-fedora.sh +0 -0
  77. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small/t3.small/t3.small.tf +0 -0
  78. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small/t3.small/terraform.tfvars +0 -0
  79. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x2/t3.small/.gitignore +0 -0
  80. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x2/t3.small/cloud-init-slurm-fedora.sh +0 -0
  81. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x2/t3.small/replace-var.sh +0 -0
  82. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x2/t3.small/t3.small.tf +0 -0
  83. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x2/t3.small/terraform.tfvars +0 -0
  84. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x3/t3.small/.gitignore +0 -0
  85. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x3/t3.small/cloud-init-slurm-fedora.sh +0 -0
  86. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x3/t3.small/t3.small.tf +0 -0
  87. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/terraform/aws-ec2-t3.small-x3/t3.small/terraform.tfvars +0 -0
  88. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/version/version.json +0 -0
  89. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/cc-gcovr.html +0 -0
  90. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/cc-intel.html +0 -0
  91. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/files.html +0 -0
  92. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/canceled.png +0 -0
  93. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/created.png +0 -0
  94. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/failed.png +0 -0
  95. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/failed_black.png +0 -0
  96. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/failed_green.png +0 -0
  97. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/file_cloud.png +0 -0
  98. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/file_config.png +0 -0
  99. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/file_ko.png +0 -0
  100. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/file_ok.png +0 -0
  101. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/skipped.png +0 -0
  102. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/squidient_logo.png +0 -0
  103. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/success.png +0 -0
  104. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/success_black.png +0 -0
  105. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/timeout.png +0 -0
  106. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/tolerance.png +0 -0
  107. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/warning.png +0 -0
  108. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/warning_black.png +0 -0
  109. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/png/warning_green.png +0 -0
  110. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/canceled.svg +0 -0
  111. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/created.svg +0 -0
  112. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/failed.svg +0 -0
  113. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/failed_black.svg +0 -0
  114. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/failed_green.svg +0 -0
  115. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/manual.svg +0 -0
  116. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/running.svg +0 -0
  117. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/skipped.svg +0 -0
  118. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/success.svg +0 -0
  119. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/success_black.svg +0 -0
  120. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/warning.svg +0 -0
  121. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/warning_black.svg +0 -0
  122. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/img/svg/warning_green.svg +0 -0
  123. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/index.html +0 -0
  124. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/jquery.dynatable.css +0 -0
  125. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/jquery.dynatable.js +0 -0
  126. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/monitoring.html +0 -0
  127. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/monitoring_build.html +0 -0
  128. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/monitoring_test.html +0 -0
  129. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/perf.html +0 -0
  130. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/staging_build.html +0 -0
  131. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/staging_test.html +0 -0
  132. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/testsuite.css +0 -0
  133. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/data/web/testsuite.js +0 -0
  134. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/definitions.py +0 -0
  135. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/deployment/initialization.py +0 -0
  136. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/deployment/module_generator.py +0 -0
  137. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/monitoring/monitoring_db.py +0 -0
  138. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/__init__.py +0 -0
  139. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/cases/__init__.py +0 -0
  140. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/cases/base.py +0 -0
  141. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/cases/case.py +0 -0
  142. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/cases/detailed.py +0 -0
  143. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/cases/full.py +0 -0
  144. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/monitoring/__init__.py +0 -0
  145. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/monitoring/report.py +0 -0
  146. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/reports/report.py +0 -0
  147. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/partition.py +0 -0
  148. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/platform.py +0 -0
  149. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/qos.py +0 -0
  150. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/queue_tester.py +0 -0
  151. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/reservation.py +0 -0
  152. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/system.py +0 -0
  153. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/systems/system_manager.py +0 -0
  154. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/terraform/terraform.py +0 -0
  155. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/benchmarks/__init__.py +0 -0
  156. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/benchmarks/instance.py +0 -0
  157. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/benchmarks/test_case.py +0 -0
  158. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/benchmarks/test_orchestrator.py +0 -0
  159. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/cases/__init__.py +0 -0
  160. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/cases/instance_merger.py +0 -0
  161. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/cases/test_case.py +0 -0
  162. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/testing/test_orchestrator.py +0 -0
  163. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/timers/__init__.py +0 -0
  164. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/timers/timer.py +0 -0
  165. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/arguments.py +0 -0
  166. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/gitlab.py +0 -0
  167. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/lock.py +0 -0
  168. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/log.py +0 -0
  169. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/message.py +0 -0
  170. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/package.py +0 -0
  171. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/utils.py +0 -0
  172. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/utils/watchdog.py +0 -0
  173. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/version_control/__init__.py +0 -0
  174. {squidient-3.0.4 → squidient-3.0.7}/src/squidient/version_control/git_repository.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: squidient
3
- Version: 3.0.4
3
+ Version: 3.0.7
4
4
  Summary: CI/CD framework for alya
5
5
  Project-URL: Homepage, https://alya.gitlab.bsc.es/alya/ci-cd/squidient
6
6
  Project-URL: Bug Tracker, https://alya.gitlab.bsc.es/alya/ci-cd/squidient/issues
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "squidient"
7
- version = "3.0.4"
7
+ version = "3.0.7"
8
8
  authors = [
9
9
  { name="Damien Dosimont", email="damien.dosimont@gmail.com" },
10
10
  ]
@@ -82,7 +82,7 @@ def _run_cli(argv: Sequence[str]) -> int:
82
82
  monitoring.init()
83
83
 
84
84
  if "validate" == argv[0]:
85
- monitoring.validate()
85
+ return 0 if monitoring.validate() else 1
86
86
 
87
87
  elif "build" == argv[0]:
88
88
  monitoring.lock(terraform)
@@ -137,7 +137,7 @@ def _run_cli(argv: Sequence[str]) -> int:
137
137
  cicd.init()
138
138
 
139
139
  if "validate" == argv[0]:
140
- cicd.validate()
140
+ return 0 if cicd.validate() else 1
141
141
 
142
142
  elif "report" == argv[0]:
143
143
  if len(argv) >= 2:
@@ -56,6 +56,27 @@ from pathlib import Path
56
56
  # Use main(argv) to run it programmatically.
57
57
 
58
58
 
59
+ def normalize_benchmark_failure_sender(sender):
60
+ if sender is None or sender == "":
61
+ return benchmark_failure_sender
62
+ return sender
63
+
64
+
65
+ def normalize_benchmark_failure_copy(recipients):
66
+ if recipients is None:
67
+ return list(benchmark_failure_copy)
68
+ if isinstance(recipients, list):
69
+ candidates = recipients
70
+ else:
71
+ candidates = str(recipients).replace(";", ",").split(",")
72
+ normalized = []
73
+ for recipient in candidates:
74
+ recipient = str(recipient).strip()
75
+ if "@" in recipient and recipient not in normalized:
76
+ normalized.append(recipient)
77
+ return normalized
78
+
79
+
59
80
  def save_field(field, value):
60
81
  config = open_json(config_file)
61
82
  value = clean_value(value)
@@ -330,7 +351,8 @@ def generate_json():
330
351
 
331
352
  def gitlab_config(pipeline, directory, alya_ref, alya_branch, flex=False, system="bsc", platform="gpp", hosts=None, install=False,
332
353
  build_selection_type=None, api=None, reservation=False, project=None, alamak=False, alamak_branch=None,
333
- alamak_revision=None, notify_failures=False):
354
+ alamak_revision=None, notify_failures=False, failure_notification_sender=None,
355
+ failure_notification_recipients=None):
334
356
 
335
357
  benchmark_presets = BuildPresets("benchmarks").get_presets()
336
358
  build_presets = BuildPresets("builds").get_presets()
@@ -383,8 +405,8 @@ def gitlab_config(pipeline, directory, alya_ref, alya_branch, flex=False, system
383
405
  console.section("Configuring flex")
384
406
  config["flex"] = flex
385
407
  config["benchmarks"]["notifyFailures"] = notify_failures
386
- config["benchmarks"]["failureSender"] = benchmark_failure_sender
387
- config["benchmarks"]["failureCopy"] = benchmark_failure_copy
408
+ config["benchmarks"]["failureSender"] = normalize_benchmark_failure_sender(failure_notification_sender)
409
+ config["benchmarks"]["failureCopy"] = normalize_benchmark_failure_copy(failure_notification_recipients)
388
410
  console.section("Configuring clean log")
389
411
  config["cleanLog"] = False
390
412
  console.section("Configuring system")
@@ -587,6 +609,8 @@ def _run_cli(argv: Sequence[str]) -> int:
587
609
  alamak_branch = None
588
610
  alamak_revision = None
589
611
  notify_failures = False
612
+ failure_notification_sender = None
613
+ failure_notification_recipients = None
590
614
 
591
615
  for arg in argv[0:]:
592
616
  if "--pipeline:" in arg:
@@ -637,6 +661,12 @@ def _run_cli(argv: Sequence[str]) -> int:
637
661
  if "--notify-failures" in arg:
638
662
  notify_failures = True
639
663
  console.step("Benchmark failure notifications enabled")
664
+ if "--failure-notification-sender:" in arg:
665
+ failure_notification_sender = arg.replace("--failure-notification-sender:", "")
666
+ console.step("Failure notification sender " + failure_notification_sender)
667
+ if "--failure-notification-recipients:" in arg:
668
+ failure_notification_recipients = arg.replace("--failure-notification-recipients:", "")
669
+ console.step("Failure notification recipients configured")
640
670
 
641
671
  gitlab_config(
642
672
  pipeline=pipeline,
@@ -656,6 +686,8 @@ def _run_cli(argv: Sequence[str]) -> int:
656
686
  alamak_branch=alamak_branch,
657
687
  alamak_revision=alamak_revision,
658
688
  notify_failures=notify_failures,
689
+ failure_notification_sender=failure_notification_sender,
690
+ failure_notification_recipients=failure_notification_recipients,
659
691
  )
660
692
  return 0
661
693
 
@@ -37,6 +37,7 @@
37
37
  <th>Job</th>
38
38
  <th>Sbatch</th>
39
39
  <th>Output</th>
40
+ <th>Binding</th>
40
41
  <th>Alya</th>
41
42
  <th>Postprocess</th>
42
43
  <th>Job Id</th>
@@ -83,6 +84,9 @@
83
84
  t[x].output_out=testsuiteJSON.setUrl(testsuiteJSON.FILE_OK, dir + "/test.out", null)
84
85
  t[x].output_err=testsuiteJSON.setUrl(testsuiteJSON.FILE_KO, dir + "/test.err", null)
85
86
  t[x].output=t[x].output_out + " " + t[x].output_err
87
+ t[x].binding_out=testsuiteJSON.setUrl(testsuiteJSON.FILE_OK, dir + "/binding.out", null)
88
+ t[x].binding_err=testsuiteJSON.setUrl(testsuiteJSON.FILE_KO, dir + "/binding.err", null)
89
+ t[x].binding=t[x].binding_out + " " + t[x].binding_err
86
90
  t[x].alya_out=testsuiteJSON.setUrl(testsuiteJSON.FILE_OK, dir + "/alya.out", null)
87
91
  t[x].alya_err=testsuiteJSON.setUrl(testsuiteJSON.FILE_KO, dir + "/alya.err", null)
88
92
  t[x].alya=t[x].alya_out + " " + t[x].alya_err
@@ -105,7 +109,7 @@
105
109
  t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_KO, dir + "/alya.err", null, 2, "Job error")
106
110
  }
107
111
  else if (t[x].error=="binding"){
108
- t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_BINDING, dir + "/alya.err", null, 3, "Binding error")
112
+ t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_BINDING, dir + "/binding.err", null, 3, "Binding error")
109
113
  }
110
114
  else if (t[x].error=="overload"){
111
115
  t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_WEIGHT, dir + "/alya.err", null, 4, "Overload error")
@@ -37,6 +37,7 @@
37
37
  <th>Job</th>
38
38
  <th>Sbatch</th>
39
39
  <th>Output</th>
40
+ <th>Binding</th>
40
41
  <th>Alya</th>
41
42
  <th>Postprocess</th>
42
43
  <th>Job Id</th>
@@ -84,6 +85,9 @@
84
85
  t[x].output_out=testsuiteJSON.setUrl(testsuiteJSON.FILE_OK, dir + "/test.out", null)
85
86
  t[x].output_err=testsuiteJSON.setUrl(testsuiteJSON.FILE_KO, dir + "/test.err", null)
86
87
  t[x].output=t[x].output_out + " " + t[x].output_err
88
+ t[x].binding_out=testsuiteJSON.setUrl(testsuiteJSON.FILE_OK, dir + "/binding.out", null)
89
+ t[x].binding_err=testsuiteJSON.setUrl(testsuiteJSON.FILE_KO, dir + "/binding.err", null)
90
+ t[x].binding=t[x].binding_out + " " + t[x].binding_err
87
91
  t[x].alya_out=testsuiteJSON.setUrl(testsuiteJSON.FILE_OK, dir + "/alya.out", null)
88
92
  t[x].alya_err=testsuiteJSON.setUrl(testsuiteJSON.FILE_KO, dir + "/alya.err", null)
89
93
  t[x].alya=t[x].alya_out + " " + t[x].alya_err
@@ -106,7 +110,7 @@
106
110
  t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_KO, dir + "/alya.err", null, 2, "Job error")
107
111
  }
108
112
  else if (t[x].error=="binding"){
109
- t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_BINDING, dir + "/alya.err", null, 3, "Binding error")
113
+ t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_BINDING, dir + "/binding.err", null, 3, "Binding error")
110
114
  }
111
115
  else if (t[x].error=="overload"){
112
116
  t[x].status=testsuiteJSON.setUrl(testsuiteJSON.SYS_WEIGHT, dir + "/alya.err", null, 4, "Overload error")
@@ -139,7 +139,7 @@ class Monitoring(Staging):
139
139
  console.error(message + "\nDetails written to " + log_path, level=1)
140
140
  if len(failures) > 0:
141
141
  raise WorkflowFailure("Benchmark notification email could not be sent")
142
- super().validate()
142
+ return super().validate()
143
143
 
144
144
  def write_notification_failure_log(self, failures):
145
145
  log_dir = os.path.dirname(benchmark_notification_failure_log)
@@ -197,8 +197,6 @@ class Monitoring(Staging):
197
197
  console.report("web/monitoring_test.html", level=1)
198
198
  print_line()
199
199
  self.clean_locks()
200
- if not status:
201
- raise WorkflowFailure("Monitoring test phase failed")
202
200
 
203
201
  def prepare_monitoring_test_builds(self, fake=False):
204
202
  if not fake:
@@ -327,8 +327,6 @@ class Staging:
327
327
  console.report("web/staging_test.html", level=1)
328
328
  print_line()
329
329
  self.clean_locks()
330
- if not status:
331
- raise WorkflowFailure("Test phase failed")
332
330
 
333
331
  def create_test_orchestrator(self):
334
332
  return TestOrchestrator(
@@ -568,10 +566,12 @@ class Staging:
568
566
  self.clean_locks()
569
567
 
570
568
  def validate(self):
569
+ console.section("Validation result")
571
570
  if self._report.get_valid():
571
+ console.success("Report is valid", level=1)
572
572
  return True
573
- else:
574
- raise WorkflowFailure("Report is not valid")
573
+ console.error("Report is not valid", level=1)
574
+ return False
575
575
 
576
576
  def report_push(self):
577
577
  with self.timer("staging.report_push", local=False, system="bsc"):
@@ -20,6 +20,7 @@
20
20
  from email.message import EmailMessage
21
21
  from ...definitions import benchmark_failure_log_files
22
22
  import os
23
+ import re
23
24
  import shutil
24
25
  import smtplib
25
26
  import subprocess
@@ -68,9 +69,24 @@ class BenchmarkFailureNotifier:
68
69
  self._from_address = from_address
69
70
  if copy_recipients is None:
70
71
  copy_recipients = []
71
- self._copy_recipients = copy_recipients
72
+ self._copy_recipients = self.normalize_recipients(copy_recipients)
72
73
  self._mail_sender = mail_sender or self.send_mail
73
74
 
75
+ @staticmethod
76
+ def normalize_recipients(recipients):
77
+ if recipients is None:
78
+ return []
79
+ if isinstance(recipients, str):
80
+ candidates = re.split(r"[,;]", recipients)
81
+ else:
82
+ candidates = recipients
83
+ normalized = []
84
+ for candidate in candidates:
85
+ candidate = str(candidate).strip()
86
+ if "@" in candidate and candidate not in normalized:
87
+ normalized.append(candidate)
88
+ return normalized
89
+
74
90
  def notify(self, report):
75
91
  recipients = self.recipients(report.get("authors", []))
76
92
  if len(recipients) == 0:
@@ -46,6 +46,8 @@ from ...utils.utils import (
46
46
 
47
47
  SBATCH_OUTPUT_FILE = "sbatch.out"
48
48
  SBATCH_ERROR_FILE = "sbatch.err"
49
+ BINDING_OUTPUT_FILE = "binding.out"
50
+ BINDING_ERROR_FILE = "binding.err"
49
51
 
50
52
 
51
53
  def file_contains(path, text):
@@ -125,6 +127,7 @@ class Instance:
125
127
  self._report = {}
126
128
 
127
129
  self._alya_cmd = ""
130
+ self._binding_cmd = ""
128
131
  self._pp_cmd = ""
129
132
  self._exec_modules = []
130
133
 
@@ -241,10 +244,13 @@ class Instance:
241
244
  alya_custom = ""
242
245
  postprocess_custom = ""
243
246
  alya_out = " >> alya.out 2>> alya.err"
247
+ binding_out = " >> " + BINDING_OUTPUT_FILE + " 2>> " + BINDING_ERROR_FILE
244
248
  run_exec = "mpirun"
245
249
  run_proc = "-np"
246
250
  run_sep = ":"
247
- alya_default = run_exec + " " + self._run_bind + " " + self._run_map + " " + self._run_options + " $" + self._binding_report + " " + run_proc + " " + self._mpi + " $ALYA " + self._name
251
+ run_prefix = run_exec + " " + self._run_bind + " " + self._run_map + " " + self._run_options
252
+ alya_default = run_prefix + " " + run_proc + " " + self._mpi + " $ALYA " + self._name
253
+ self._binding_cmd = 'if [ -n "$' + self._binding_report + '" ]; then ' + run_prefix + " $" + self._binding_report + " " + run_proc + " " + self._mpi + " /bin/true" + binding_out + "; fi"
248
254
  postprocess_output_redirect = " >> post.out 2>> post.err"
249
255
  postprocess_default = 'echo "Nothing to do"'
250
256
  postprocess_command = ""
@@ -272,7 +278,7 @@ class Instance:
272
278
  if "postprocess" in self._execution["commands"]:
273
279
  postprocess_custom = self._execution["commands"]["postprocess"]
274
280
  if alya_custom != "":
275
- alya_custom = alya_custom.replace("[RUN]", run_exec + " " + self._run_bind + " " + self._run_map + " " + self._run_options)
281
+ alya_custom = alya_custom.replace("[RUN]", run_prefix)
276
282
  alya_custom = alya_custom.replace("[NP]", run_proc)
277
283
  alya_custom = alya_custom.replace("[MPI]", self._mpi)
278
284
  alya_custom = alya_custom.replace("[NAME]", self._name)
@@ -367,8 +373,8 @@ class Instance:
367
373
  self._script += pre_exec + "\n"
368
374
  self._script += 'if mpirun -V | grep "Open MPI"; then export ' + self._binding_report + '="--report-bindings"' + "; fi\n"
369
375
  self._script += 'if mpirun -V | grep "Intel"; then export ' + self._binding_report + '="-print-rank-map"' + "; fi\n"
370
- self._script += "echo $" + self._binding_report + "\n"
371
- self._script += "rm -f alya.out alya.err infiniband.out\n"
376
+ self._script += "rm -f alya.out alya.err " + BINDING_OUTPUT_FILE + " " + BINDING_ERROR_FILE + " infiniband.out\n"
377
+ self._script += self._binding_cmd + "\n"
372
378
  self._script += "cat /sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_data > infiniband.out\n"
373
379
  self._script += "cat /sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_data >> infiniband.out\n"
374
380
  self._script += "date '+%s' >> time.out\n"
@@ -491,7 +497,10 @@ class Instance:
491
497
  self.retry()
492
498
  elif file_contains(self._report_path + "/alya.err", "All nodes which are allocated for this job are already filled"):
493
499
  self._report["error"] = "overload"
494
- elif file_contains(self._report_path + "/alya.err", "A request was made to bind to that would result in binding more"):
500
+ elif (
501
+ file_contains(self._report_path + "/" + BINDING_ERROR_FILE, "A request was made to bind to that would result in binding more")
502
+ or file_contains(self._report_path + "/alya.err", "A request was made to bind to that would result in binding more")
503
+ ):
495
504
  self._report["error"] = "binding"
496
505
  elif file_contains(self._report_path + "/alya.err", "Integer overflow in xmallocarray"):
497
506
  self.retry()
@@ -646,6 +655,8 @@ class Instance:
646
655
  open(self._report_path + "/test.err", 'a+').close()
647
656
  open(self._report_path + "/alya.out", 'a+').close()
648
657
  open(self._report_path + "/alya.err", 'a+').close()
658
+ open(self._report_path + "/" + BINDING_OUTPUT_FILE, 'a+').close()
659
+ open(self._report_path + "/" + BINDING_ERROR_FILE, 'a+').close()
649
660
  open(self._report_path + "/post.out", 'a+').close()
650
661
  open(self._report_path + "/post.err", 'a+').close()
651
662
  open(self._report_path + "/" + SBATCH_OUTPUT_FILE, 'a+').close()
@@ -659,6 +670,8 @@ class Instance:
659
670
  "test.err",
660
671
  "alya.out",
661
672
  "alya.err",
673
+ BINDING_OUTPUT_FILE,
674
+ BINDING_ERROR_FILE,
662
675
  "post.out",
663
676
  "post.err",
664
677
  SBATCH_OUTPUT_FILE,
File without changes
File without changes
File without changes