gitlabform 6.3.0__tar.gz → 6.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.
Files changed (280) hide show
  1. {gitlabform-6.3.0 → gitlabform-6.3.1}/PKG-INFO +2 -2
  2. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/changelog.md +16 -0
  3. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/implementation_design.md +1 -1
  4. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/__init__.py +0 -4
  5. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/core.py +0 -11
  6. gitlabform-6.3.1/gitlabform/processors/project/merge_requests_approval_rules.py +158 -0
  7. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/util.py +3 -0
  8. {gitlabform-6.3.0 → gitlabform-6.3.1}/pyproject.toml +7 -7
  9. {gitlabform-6.3.0 → gitlabform-6.3.1}/tbump.toml +1 -1
  10. gitlabform-6.3.1/tests/unit/configuration/transform/test_convert_to_simple_types.py +19 -0
  11. gitlabform-6.3.1/tests/unit/processors/test_merge_requests_approval_rules_processor.py +364 -0
  12. {gitlabform-6.3.0 → gitlabform-6.3.1}/uv.lock +75 -74
  13. gitlabform-6.3.0/gitlabform/gitlab/project_merge_requests_approvals.py +0 -94
  14. gitlabform-6.3.0/gitlabform/processors/project/merge_requests_approval_rules.py +0 -38
  15. gitlabform-6.3.0/tests/unit/processors/test_merge_requests_approval_rules_processor.py +0 -120
  16. {gitlabform-6.3.0 → gitlabform-6.3.1}/.coveragerc +0 -0
  17. {gitlabform-6.3.0 → gitlabform-6.3.1}/.dockerignore +0 -0
  18. {gitlabform-6.3.0 → gitlabform-6.3.1}/.git-blame-ignore-revs +0 -0
  19. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/CODEOWNERS +0 -0
  20. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  21. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  22. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/ISSUE_TEMPLATE/question-or-other-issue.md +0 -0
  23. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/actions/setup-uv-local/README.md +0 -0
  24. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/actions/setup-uv-local/action.yml +0 -0
  25. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/dependabot.yml +0 -0
  26. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/_main.yml +0 -0
  27. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/_releases.yml +0 -0
  28. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/build.yml +0 -0
  29. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/codecov-upload.yml +0 -0
  30. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/pr-ci-workflow.yml +0 -0
  31. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/prs-entrypoint-forks.yml +0 -0
  32. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/prs-entrypoint-main.yml +0 -0
  33. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/static-analysis.yml +0 -0
  34. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/tests-acceptance.yml +0 -0
  35. {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/tests-unit.yml +0 -0
  36. {gitlabform-6.3.0 → gitlabform-6.3.1}/.gitignore +0 -0
  37. {gitlabform-6.3.0 → gitlabform-6.3.1}/.lgtm.yml +0 -0
  38. {gitlabform-6.3.0 → gitlabform-6.3.1}/.mypy.ini +0 -0
  39. {gitlabform-6.3.0 → gitlabform-6.3.1}/.overrides/gitlabform-logo-favicon.png +0 -0
  40. {gitlabform-6.3.0 → gitlabform-6.3.1}/.overrides/gitlabform-logo-favicon.svg +0 -0
  41. {gitlabform-6.3.0 → gitlabform-6.3.1}/.python-version +0 -0
  42. {gitlabform-6.3.0 → gitlabform-6.3.1}/CONTRIBUTING.md +0 -0
  43. {gitlabform-6.3.0 → gitlabform-6.3.1}/Dockerfile +0 -0
  44. {gitlabform-6.3.0 → gitlabform-6.3.1}/LICENSE +0 -0
  45. {gitlabform-6.3.0 → gitlabform-6.3.1}/README.md +0 -0
  46. {gitlabform-6.3.0 → gitlabform-6.3.1}/codecov.yml +0 -0
  47. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/__init__.py +0 -0
  48. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/common.py +0 -0
  49. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/docker.py +0 -0
  50. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/docs.py +0 -0
  51. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/env.py +0 -0
  52. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/await-healthy.sh +0 -0
  53. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/gitlab.rb +0 -0
  54. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/healthcheck-and-setup.sh +0 -0
  55. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/run_gitlab_in_docker.sh +0 -0
  56. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/tests.Dockerfile +0 -0
  57. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/infra.py +0 -0
  58. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/main.py +0 -0
  59. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/package.py +0 -0
  60. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/qa.py +0 -0
  61. {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/release.py +0 -0
  62. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/automation.md +0 -0
  63. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/coding_guidelines.md +0 -0
  64. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/index.md +0 -0
  65. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/local_development.md +0 -0
  66. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/releases.md +0 -0
  67. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/workflows.md +0 -0
  68. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/features.md +0 -0
  69. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/Opencast-logo.png +0 -0
  70. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/egnyte-logo.svg +0 -0
  71. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/elastic-path-logo.svg +0 -0
  72. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/gitlabform-logo-square.png +0 -0
  73. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/gitlabform-logo.png +0 -0
  74. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/gitlabform-logo.svg +0 -0
  75. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/group-ldap-links-provider.png +0 -0
  76. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/liquidlight-logo.svg +0 -0
  77. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/roche-logo.png +0 -0
  78. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/stroeer-online-marketing-logo.svg +0 -0
  79. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/ti8m-logo.png +0 -0
  80. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/index.md +0 -0
  81. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/installation.md +0 -0
  82. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/archive_unarchive.md +0 -0
  83. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/avatar.md +0 -0
  84. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/badges.md +0 -0
  85. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/ci_cd_variables.md +0 -0
  86. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/deploy_keys.md +0 -0
  87. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/files.md +0 -0
  88. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/group_ldap_links.md +0 -0
  89. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/group_saml_links.md +0 -0
  90. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/index.md +0 -0
  91. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/integrations.md +0 -0
  92. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/job_token_scope.md +0 -0
  93. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/labels.md +0 -0
  94. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/members.md +0 -0
  95. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/merge_requests.md +0 -0
  96. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/pipeline_schedules.md +0 -0
  97. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/project_security_settings.md +0 -0
  98. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/project_transfer.md +0 -0
  99. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/protected_branches.md +0 -0
  100. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/protected_environments.md +0 -0
  101. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/push_mirrors.md +0 -0
  102. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/push_rules.md +0 -0
  103. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/resource_groups.md +0 -0
  104. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/settings.md +0 -0
  105. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/tags_protection.md +0 -0
  106. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/webhooks.md +0 -0
  107. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/requirements.md +0 -0
  108. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/running.md +0 -0
  109. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/similar_apps.md +0 -0
  110. {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/upgrade.md +0 -0
  111. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlab-config/config.yml +0 -0
  112. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlab-config/gitlab-config.md +0 -0
  113. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/__init__.py +0 -0
  114. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/__init__.py +0 -0
  115. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/common.py +0 -0
  116. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/core.py +0 -0
  117. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/groups.py +0 -0
  118. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/projects.py +0 -0
  119. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/transform.py +0 -0
  120. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/constants.py +0 -0
  121. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/commits.py +0 -0
  122. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/groups.py +0 -0
  123. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/merge_requests.py +0 -0
  124. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/pipelines.py +0 -0
  125. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/projects.py +0 -0
  126. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/python_gitlab.py +0 -0
  127. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/variables.py +0 -0
  128. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/__init__.py +0 -0
  129. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/filter.py +0 -0
  130. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/groups.py +0 -0
  131. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/projects.py +0 -0
  132. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/output.py +0 -0
  133. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/__init__.py +0 -0
  134. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/abstract_processor.py +0 -0
  135. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/application/__init__.py +0 -0
  136. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/application/application_settings_processor.py +0 -0
  137. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/defining_keys.py +0 -0
  138. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/__init__.py +0 -0
  139. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_badges_processor.py +0 -0
  140. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_hooks_processor.py +0 -0
  141. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_labels_processor.py +0 -0
  142. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
  143. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_members_processor.py +0 -0
  144. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_protected_branches_processor.py +0 -0
  145. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_push_rules_processor.py +0 -0
  146. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_saml_links_processor.py +0 -0
  147. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_settings_processor.py +0 -0
  148. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_variables_processor.py +0 -0
  149. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/multiple_entities_processor.py +0 -0
  150. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/__init__.py +0 -0
  151. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/badges_processor.py +0 -0
  152. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/branches_processor.py +0 -0
  153. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
  154. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/files_processor.py +0 -0
  155. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/hooks_processor.py +0 -0
  156. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/integrations_processor.py +0 -0
  157. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
  158. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/members_processor.py +0 -0
  159. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
  160. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_labels_processor.py +0 -0
  161. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_processor.py +0 -0
  162. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
  163. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_security_settings.py +0 -0
  164. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_settings_processor.py +0 -0
  165. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_variables_processor.py +0 -0
  166. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/protected_environments_processor.py +0 -0
  167. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/remote_mirrors_processor.py +0 -0
  168. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/resource_groups_processor.py +0 -0
  169. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/schedules_processor.py +0 -0
  170. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/tags_processor.py +0 -0
  171. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/__init__.py +0 -0
  172. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/badges_processor.py +0 -0
  173. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/branch_protection.py +0 -0
  174. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/decorators.py +0 -0
  175. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/difference_logger.py +0 -0
  176. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/labels_processor.py +0 -0
  177. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/variables_processor.py +0 -0
  178. {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/run.py +0 -0
  179. {gitlabform-6.3.0 → gitlabform-6.3.1}/mkdocs.yml +0 -0
  180. {gitlabform-6.3.0 → gitlabform-6.3.1}/prek.toml +0 -0
  181. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/__init__.py +0 -0
  182. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/__init__.py +0 -0
  183. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/conftest.py +0 -0
  184. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_branches.py +0 -0
  185. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_branches_users_case_insensitive.py +0 -0
  186. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_ldap_links.py +0 -0
  187. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_protected_branches.py +0 -0
  188. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_push_rules.py +0 -0
  189. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_saml_links.py +0 -0
  190. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_settings.py +0 -0
  191. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_variables.py +0 -0
  192. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_merge_request_approval_rules.py +0 -0
  193. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_merge_request_approvals_settings.py +0 -0
  194. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_protected_environments.py +0 -0
  195. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_push_rules.py +0 -0
  196. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_tags.py +0 -0
  197. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/__init__.py +0 -0
  198. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_application_settings.py +0 -0
  199. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_archive_project.py +0 -0
  200. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_badges.py +0 -0
  201. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_branches.py +0 -0
  202. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_deploy_keys.py +0 -0
  203. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_deploy_keys_all_projects.py +0 -0
  204. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_files.py +0 -0
  205. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_files_templates.py +0 -0
  206. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_avatar.py +0 -0
  207. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_badges.py +0 -0
  208. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_hooks.py +0 -0
  209. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_labels.py +0 -0
  210. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_members_case_insensitive.py +0 -0
  211. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_members_groups.py +0 -0
  212. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_members_users.py +0 -0
  213. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_settings.py +0 -0
  214. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_variables.py +0 -0
  215. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_hooks.py +0 -0
  216. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_integrations.py +0 -0
  217. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_job_token_scope.py +0 -0
  218. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_members.py +0 -0
  219. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_members_add_group.py +0 -0
  220. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_members_enforce.py +0 -0
  221. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_avatar.py +0 -0
  222. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_group_members_case_insensitive.py +0 -0
  223. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_labels.py +0 -0
  224. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_members_case_insensitve.py +0 -0
  225. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_settings.py +0 -0
  226. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_variables.py +0 -0
  227. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_remote_mirrors.py +0 -0
  228. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_resource_groups.py +0 -0
  229. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_running.py +0 -0
  230. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_scheduled_for_deletion_project.py +0 -0
  231. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_schedules.py +0 -0
  232. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_tags.py +0 -0
  233. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_token_from_config.py +0 -0
  234. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_transfer_project.py +0 -0
  235. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_wildcard_patterns.py +0 -0
  236. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_group_members.py +0 -0
  237. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_group_settings.py +0 -0
  238. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_members.py +0 -0
  239. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_project_security_settings.py +0 -0
  240. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_project_settings.py +0 -0
  241. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/__init__.py +0 -0
  242. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/__init__.py +0 -0
  243. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_case_sensitivity.py +0 -0
  244. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_inheritance_break_projects_and_groups.py +0 -0
  245. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_inheritance_break_subgroups.py +0 -0
  246. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_inheritance_break_validation.py +0 -0
  247. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_projects_and_groups.py +0 -0
  248. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_skip_groups_skip_projects.py +0 -0
  249. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_subgroups.py +0 -0
  250. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_wildcard_patterns.py +0 -0
  251. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_yaml_version.py +0 -0
  252. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_access_level_transformer.py +0 -0
  253. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_group_transformer.py +0 -0
  254. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_implicit_name_transformer.py +0 -0
  255. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_user_and_group_transformers.py +0 -0
  256. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_user_transformer.py +0 -0
  257. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/gitlab/test_core.py +0 -0
  258. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/gitlab/test_groups.py +0 -0
  259. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/gitlab/test_python_gitlab.py +0 -0
  260. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/__init__.py +0 -0
  261. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_abstract_processor.py +0 -0
  262. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_abstract_processors.py +0 -0
  263. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_branches_processor.py +0 -0
  264. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_deploy_keys_processor.py +0 -0
  265. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_difference_logger.py +0 -0
  266. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_files_processor.py +0 -0
  267. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_ldap_links_processor.py +0 -0
  268. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_members_processor.py +0 -0
  269. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_protected_branches_processor.py +0 -0
  270. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_saml_links_processor.py +0 -0
  271. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_protected_environments_processor.py +0 -0
  272. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_schedules_processor_extended_cron_pattern.py +0 -0
  273. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_util_badges_processor.py +0 -0
  274. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_access_levels.py +0 -0
  275. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_non_empty_configs_provider.py +0 -0
  276. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_output.py +0 -0
  277. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_parse_args.py +0 -0
  278. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_projects_provider.py +0 -0
  279. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_show_summary.py +0 -0
  280. {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gitlabform
3
- Version: 6.3.0
3
+ Version: 6.3.1
4
4
  Summary: 🏗 Specialized configuration as a code tool for GitLab projects, groups and more using hierarchical configuration written in YAML
5
5
  Project-URL: Homepage, https://gitlabform.github.io/gitlabform/
6
6
  Project-URL: Repository, https://github.com/gitlabform/gitlabform.git
@@ -19,7 +19,7 @@ Classifier: Operating System :: POSIX :: Linux
19
19
  Classifier: Programming Language :: Python :: 3.14
20
20
  Classifier: Topic :: Software Development :: Version Control :: Git
21
21
  Requires-Python: >=3.12.0
22
- Requires-Dist: certifi==2026.7.22
22
+ Requires-Dist: certifi==2026.10.23
23
23
  Requires-Dist: cli-ui==0.19.0
24
24
  Requires-Dist: jinja2==3.1.6
25
25
  Requires-Dist: luddite==1.0.4
@@ -6,6 +6,22 @@ For details on how to migrate between major versions, please refer to the [upgra
6
6
 
7
7
  ---
8
8
 
9
+ ## 6.3.1
10
+
11
+ ### Bug Fixes
12
+
13
+ * keep long configuration values from being wrapped [#1470](https://github.com/gitlabform/gitlabform/pull/1470). ([robertrotaru](https://github.com/robertrotaru))
14
+
15
+ ### Refactors
16
+
17
+ * migrate merge requests approval rules processor to python-gitlab [#1459](https://github.com/gitlabform/gitlabform/pull/1459). ([rickbrouwer](https://github.com/rickbrouwer))
18
+
19
+ ### Dependencies
20
+
21
+ * Update various dependencies to newer versions.
22
+
23
+ Thanks to all the contributors of this release!
24
+
9
25
  ## 6.3.0
10
26
 
11
27
  ### Features
@@ -99,7 +99,7 @@ Sometimes there is some logic in these methods if:
99
99
 
100
100
  * we only need a specific part of the response from GitLab API - see `GitLabProjects.get_all_projects()` as an example,
101
101
  * some GitLab APIs need some workarounds for their bugs or documentation inconsistencies, like:
102
- * some APIs declare in the docs that they accept both "group/project" string OR a project id while in fact only the latter works - see `GitLabProjects.post_approvals()` as an example,
102
+ * some APIs declare in the docs that they accept both "group/project" string OR a project id while in fact only the latter works,
103
103
  * some APIs return invalid HTTP error codes, like 404 instead of 400 - see `GroupLDAPLinksProcessor._create_link` as an example.
104
104
 
105
105
  **Note**: Some of the code here is **NOT used by the GitLabForm app**, but utilized by internal Egnyte
@@ -11,9 +11,6 @@ from gitlabform.gitlab.groups import GitLabGroups
11
11
  from gitlabform.gitlab.merge_requests import GitLabMergeRequests
12
12
  from gitlabform.gitlab.pipelines import GitLabPipelines
13
13
  from gitlabform.gitlab.projects import GitLabProjects
14
- from gitlabform.gitlab.project_merge_requests_approvals import (
15
- GitLabProjectMergeRequestsApprovals,
16
- )
17
14
  from gitlabform.gitlab.python_gitlab import PythonGitlab
18
15
 
19
16
 
@@ -51,7 +48,6 @@ class GitLab(
51
48
  GitLabMergeRequests,
52
49
  GitLabPipelines,
53
50
  GitLabProjects,
54
- GitLabProjectMergeRequestsApprovals,
55
51
  ):
56
52
  pass
57
53
 
@@ -157,17 +157,6 @@ class GitLabCore:
157
157
  group = self._make_requests_to_api("groups/%s?with_projects=false", path, "GET")
158
158
  return int(group["id"])
159
159
 
160
- @functools.lru_cache()
161
- def _get_protected_branch_id(self, project_and_group_name, branch) -> int:
162
- branch = self._make_requests_to_api("projects/%s/protected_branches/%s", (project_and_group_name, branch))
163
- return int(branch["id"])
164
-
165
- @functools.lru_cache()
166
- def _get_project_id(self, project_and_group):
167
- # This is a NEW workaround for https://github.com/gitlabhq/gitlabhq/issues/8290
168
- result = self.get_project(project_and_group)
169
- return str(result["id"])
170
-
171
160
  def _make_requests_to_api(
172
161
  self,
173
162
  path_as_format_string,
@@ -0,0 +1,158 @@
1
+ import sys
2
+ from logging import critical, info
3
+ from typing import Dict, List
4
+
5
+ from gitlab.exceptions import GitlabGetError
6
+ from gitlab.v4.objects import Project, ProjectApprovalRule
7
+
8
+ from gitlabform.constants import EXIT_INVALID_INPUT
9
+ from gitlabform.gitlab import GitLab
10
+ from gitlabform.processors.abstract_processor import AbstractProcessor
11
+
12
+
13
+ class MergeRequestsApprovalRules(AbstractProcessor):
14
+ def __init__(self, gitlab: GitLab):
15
+ super().__init__("merge_requests_approval_rules", gitlab)
16
+
17
+ def _process_configuration(self, project_and_group: str, configuration: Dict):
18
+ # copy, so that popping "enforce" does not mutate the shared configuration,
19
+ # which is reused when this method is retried
20
+ configured_rules: Dict = dict(configuration.get("merge_requests_approval_rules", {}))
21
+ enforce = configured_rules.pop("enforce", False)
22
+
23
+ # Rules are matched against GitLab by name, so entries sharing a name would
24
+ # reconcile ambiguously; reject them before any changes are made.
25
+ self._fail_on_duplicate_names(project_and_group, configured_rules)
26
+
27
+ project: Project = self.gl.get_project_by_path_cached(project_and_group)
28
+ existing_rules: List[ProjectApprovalRule] = project.approvalrules.list(get_all=True)
29
+
30
+ # Resolve branch names to ids before anything is deleted, so that a bad branch
31
+ # name in the config fails the section before it can remove existing rules,
32
+ # and so that each unique branch is fetched only once.
33
+ protected_branch_ids = self._protected_branch_ids(project, configured_rules)
34
+
35
+ if enforce:
36
+ # Delete stale rules before adding new ones, so that unique-constraint slots
37
+ # (e.g. only one any_approver rule per project) are freed for the rules below.
38
+ configured_names = {c.get("name") for c in configured_rules.values() if c.get("name")}
39
+ for existing in existing_rules:
40
+ if existing.name not in configured_names:
41
+ info(
42
+ f"Deleting rule '{existing.name}' of {self.configuration_name} in {project_and_group}"
43
+ f" as it's not in config and enforce is set to true."
44
+ )
45
+ existing.delete()
46
+ existing_rules = [rule for rule in existing_rules if rule.name in configured_names]
47
+
48
+ for entity_name, rule_config in configured_rules.items():
49
+ name = rule_config.get("name")
50
+ matching = next((rule for rule in existing_rules if rule.name == name), None)
51
+
52
+ if rule_config.get("delete", False):
53
+ if matching:
54
+ info(f"Deleting {entity_name} of {self.configuration_name} in {project_and_group}")
55
+ matching.delete()
56
+ else:
57
+ info(
58
+ f"Not deleting {entity_name} of {self.configuration_name} in {project_and_group},"
59
+ f" because it doesn't exist"
60
+ )
61
+ continue
62
+
63
+ if matching:
64
+ if self._needs_update(matching.asdict(), rule_config):
65
+ info(f" * Editing {entity_name} of {self.configuration_name} in {project_and_group}")
66
+ project.approvalrules.update(
67
+ matching.id, self._payload_for_update(rule_config, protected_branch_ids)
68
+ )
69
+ else:
70
+ info(
71
+ f" * {entity_name} of {self.configuration_name} in {project_and_group}"
72
+ f" doesn't need an update."
73
+ )
74
+ else:
75
+ info(f" * Adding {entity_name} of {self.configuration_name} in {project_and_group}")
76
+ project.approvalrules.create(self._payload_for_create(rule_config, protected_branch_ids))
77
+
78
+ def _needs_update(self, entity_in_gitlab: Dict, entity_in_configuration: Dict) -> bool:
79
+ # GitLab returns users/groups as lists of objects and protected_branches as list
80
+ # of objects with a "name" field, while the config (post-transform) has user_ids /
81
+ # group_ids as int lists and protected_branches as list of names. Without
82
+ # normalization the base _needs_update always triggers an update, even when nothing
83
+ # changed. We normalize both sides unconditionally so keys line up regardless of
84
+ # whether GitLab omitted an empty list or the user omitted the field in config.
85
+ gitlab_norm = dict(entity_in_gitlab)
86
+ gitlab_norm["user_ids"] = sorted(u["id"] for u in gitlab_norm.pop("users", []))
87
+ gitlab_norm["group_ids"] = sorted(g["id"] for g in gitlab_norm.pop("groups", []))
88
+ gitlab_protected_branches = gitlab_norm.pop("protected_branches", [])
89
+
90
+ # The update payload still sends omitted user_ids/group_ids/protected_branches as
91
+ # empty lists (old behavior, kept until #1468), so the comparison here has to
92
+ # mirror what _payload_for_update will send, or a rule would never converge.
93
+ # "delete" is a gitlabform control key, not a rule attribute.
94
+ config_norm = dict(entity_in_configuration)
95
+ config_norm.pop("delete", None)
96
+ config_norm["user_ids"] = sorted(config_norm.get("user_ids", []))
97
+ config_norm["group_ids"] = sorted(config_norm.get("group_ids", []))
98
+
99
+ # The config can reference branches by name (protected_branches) or directly
100
+ # by id (protected_branch_ids); compare whichever representation it uses.
101
+ if "protected_branch_ids" in config_norm:
102
+ gitlab_norm["protected_branch_ids"] = sorted(b["id"] for b in gitlab_protected_branches)
103
+ config_norm["protected_branch_ids"] = sorted(config_norm["protected_branch_ids"])
104
+ if "protected_branch_ids" not in config_norm or "protected_branches" in config_norm:
105
+ gitlab_norm["protected_branches"] = sorted(b["name"] for b in gitlab_protected_branches)
106
+ config_norm["protected_branches"] = sorted(config_norm.get("protected_branches", []))
107
+
108
+ return super()._needs_update(gitlab_norm, config_norm)
109
+
110
+ def _fail_on_duplicate_names(self, project_and_group: str, configured_rules: Dict) -> None:
111
+ names = [rule_config.get("name") for rule_config in configured_rules.values() if rule_config.get("name")]
112
+ duplicates = {name for name in names if names.count(name) > 1}
113
+ if duplicates:
114
+ critical(
115
+ f"Entities in {self.configuration_name} for {project_and_group}"
116
+ f" share the same name(s): {sorted(duplicates)}"
117
+ )
118
+ sys.exit(EXIT_INVALID_INPUT)
119
+
120
+ @staticmethod
121
+ def _protected_branch_ids(project: Project, configured_rules: Dict) -> Dict[str, int]:
122
+ branch_names = {
123
+ branch_name
124
+ for rule_config in configured_rules.values()
125
+ if not rule_config.get("delete", False)
126
+ for branch_name in rule_config.get("protected_branches", [])
127
+ }
128
+ if not branch_names:
129
+ return {}
130
+
131
+ existing = {branch.name: branch.id for branch in project.protectedbranches.list(get_all=True)}
132
+ missing = branch_names - existing.keys()
133
+ if missing:
134
+ raise GitlabGetError(
135
+ f"Protected branches {sorted(missing)} not found in this project",
136
+ response_code=404,
137
+ )
138
+ return {branch_name: existing[branch_name] for branch_name in branch_names}
139
+
140
+ @staticmethod
141
+ def _payload_for_create(rule_config: Dict, protected_branch_ids: Dict[str, int]) -> Dict:
142
+ # "delete" is a gitlabform control key and should not be sent to the API
143
+ payload = {k: v for k, v in rule_config.items() if k != "delete"}
144
+ if "protected_branches" in payload:
145
+ # the API expects protected_branch_ids, while the config has branch names
146
+ branch_names = payload.pop("protected_branches")
147
+ payload["protected_branch_ids"] = [protected_branch_ids[branch_name] for branch_name in branch_names]
148
+ return payload
149
+
150
+ def _payload_for_update(self, rule_config: Dict, protected_branch_ids: Dict[str, int]) -> Dict:
151
+ payload = self._payload_for_create(rule_config, protected_branch_ids)
152
+ # GitLab interprets omitted user_ids/group_ids/protected_branch_ids as "no change",
153
+ # but the old code sent them as empty lists, clearing them. That behavior is kept
154
+ # for now; changing it is a breaking change, tracked in #1468.
155
+ payload.setdefault("user_ids", [])
156
+ payload.setdefault("group_ids", [])
157
+ payload.setdefault("protected_branch_ids", [])
158
+ return payload
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import sys
2
3
  from datetime import date
3
4
  from io import StringIO
4
5
 
@@ -46,6 +47,8 @@ def configure_ruamel_yaml_loader(typ=None, pure=False, output=None, plug_ins=Non
46
47
  yaml_loader.indent(mapping=3, sequence=2, offset=0)
47
48
  yaml_loader.allow_duplicate_keys = True
48
49
  yaml_loader.explicit_start = False
50
+ # never wrap long scalars: a wrapped double-quoted string that is reloaded can gain spaces after backslash escapes
51
+ yaml_loader.width = sys.maxsize
49
52
  # show null
50
53
  yaml_loader.representer.add_representer(
51
54
  type(None),
@@ -10,7 +10,7 @@ packages = ["gitlabform"]
10
10
 
11
11
  [project]
12
12
  name = "gitlabform"
13
- version = "6.3.0"
13
+ version = "6.3.1"
14
14
  requires-python = ">=3.12.0"
15
15
  authors = [{ name = "Greg Dubicki and Contributors" }]
16
16
  description = "🏗 Specialized configuration as a code tool for GitLab projects, groups and more using hierarchical configuration written in YAML"
@@ -31,7 +31,7 @@ classifiers = [
31
31
 
32
32
  # Main runtime dependencies. Pinned strictly to ensure production stability.
33
33
  dependencies = [
34
- "certifi==2026.7.22",
34
+ "certifi==2026.10.23",
35
35
  "cli-ui==0.19.0",
36
36
  "jinja2==3.1.6",
37
37
  "luddite==1.0.4",
@@ -53,7 +53,7 @@ dev = [
53
53
  { include-group = "lint" },
54
54
  { include-group = "docs" },
55
55
  { include-group = "release" },
56
- "commitizen==4.18.1",
56
+ "commitizen==4.19.0",
57
57
  "prek==0.5.3",
58
58
  ]
59
59
  # Minimum set of dependencies required to execute the test suite.
@@ -68,19 +68,19 @@ test = [
68
68
  # Static analysis and formatting tools.
69
69
  lint = [
70
70
  "bandit==1.9.4",
71
- "black==26.5.1",
71
+ "black==26.10.1",
72
72
  "codespell==2.4.3",
73
73
  "mypy==2.3.1",
74
74
  "mypy-extensions==1.1.0",
75
- "ruff==0.16.8",
75
+ "ruff==0.16.9",
76
76
  "types-requests==2.33.0.20260906",
77
77
  ]
78
78
  # Documentation generation stack.
79
79
  docs = [
80
80
  "markdown==3.10.3",
81
- "zensical==0.0.62",
81
+ "zensical==0.0.65",
82
82
  "pygments==2.21.0",
83
- "pymdown-extensions==12.0.1",
83
+ "pymdown-extensions==12.1",
84
84
  ]
85
85
  # Tools required for building and verifying releases.
86
86
  release = [
@@ -2,7 +2,7 @@
2
2
  github_url = "https://github.com/gitlabform/gitlabform/"
3
3
 
4
4
  [version]
5
- current = "6.3.0"
5
+ current = "6.3.1"
6
6
 
7
7
  # Example of a semver regexp.
8
8
  # Make sure this matches current_version before
@@ -0,0 +1,19 @@
1
+ from gitlabform.configuration import Configuration
2
+ from gitlabform.configuration.transform import ConfigurationTransformer
3
+
4
+ LONG_REGEX = "^(feat|fix|chore|docs|refactor|test|ci|build|perf)(\\([^)]+\\))?!?: [A-Z][A-Z0-9]{1,9}-\\d+ .+"
5
+
6
+
7
+ def test__convert_to_simple_types_keeps_long_regex_with_escapes_intact() -> None:
8
+ config_yaml = f"""
9
+ projects_and_groups:
10
+ "foo/bar":
11
+ project_settings:
12
+ merge_request_title_regex: "{LONG_REGEX.replace(chr(92), chr(92) * 2)}"
13
+ """
14
+ configuration = Configuration(config_string=config_yaml)
15
+
16
+ ConfigurationTransformer.convert_to_simple_types(configuration)
17
+
18
+ project_settings = configuration.config["projects_and_groups"]["foo/bar"]["project_settings"]
19
+ assert project_settings["merge_request_title_regex"] == LONG_REGEX