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.
- {gitlabform-6.3.0 → gitlabform-6.3.1}/PKG-INFO +2 -2
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/changelog.md +16 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/implementation_design.md +1 -1
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/__init__.py +0 -4
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/core.py +0 -11
- gitlabform-6.3.1/gitlabform/processors/project/merge_requests_approval_rules.py +158 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/util.py +3 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/pyproject.toml +7 -7
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tbump.toml +1 -1
- gitlabform-6.3.1/tests/unit/configuration/transform/test_convert_to_simple_types.py +19 -0
- gitlabform-6.3.1/tests/unit/processors/test_merge_requests_approval_rules_processor.py +364 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/uv.lock +75 -74
- gitlabform-6.3.0/gitlabform/gitlab/project_merge_requests_approvals.py +0 -94
- gitlabform-6.3.0/gitlabform/processors/project/merge_requests_approval_rules.py +0 -38
- gitlabform-6.3.0/tests/unit/processors/test_merge_requests_approval_rules_processor.py +0 -120
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.coveragerc +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.dockerignore +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.git-blame-ignore-revs +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/CODEOWNERS +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/ISSUE_TEMPLATE/question-or-other-issue.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/actions/setup-uv-local/README.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/actions/setup-uv-local/action.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/dependabot.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/_main.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/_releases.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/build.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/codecov-upload.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/pr-ci-workflow.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/prs-entrypoint-forks.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/prs-entrypoint-main.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/static-analysis.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/tests-acceptance.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.github/workflows/tests-unit.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.gitignore +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.lgtm.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.mypy.ini +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.overrides/gitlabform-logo-favicon.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.overrides/gitlabform-logo-favicon.svg +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/.python-version +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/CONTRIBUTING.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/Dockerfile +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/LICENSE +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/README.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/codecov.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/common.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/docker.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/docs.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/env.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/await-healthy.sh +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/gitlab.rb +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/healthcheck-and-setup.sh +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/run_gitlab_in_docker.sh +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/gitlab/tests.Dockerfile +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/infra.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/main.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/package.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/qa.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/dev/release.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/automation.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/coding_guidelines.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/index.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/local_development.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/releases.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/contrib/workflows.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/features.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/Opencast-logo.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/egnyte-logo.svg +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/elastic-path-logo.svg +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/gitlabform-logo-square.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/gitlabform-logo.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/gitlabform-logo.svg +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/group-ldap-links-provider.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/liquidlight-logo.svg +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/roche-logo.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/stroeer-online-marketing-logo.svg +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/images/ti8m-logo.png +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/index.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/installation.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/archive_unarchive.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/avatar.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/badges.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/ci_cd_variables.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/deploy_keys.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/files.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/group_ldap_links.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/group_saml_links.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/index.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/integrations.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/job_token_scope.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/labels.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/members.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/merge_requests.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/pipeline_schedules.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/project_security_settings.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/project_transfer.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/protected_branches.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/protected_environments.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/push_mirrors.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/push_rules.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/resource_groups.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/settings.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/tags_protection.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/reference/webhooks.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/requirements.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/running.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/similar_apps.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/docs/upgrade.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlab-config/config.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlab-config/gitlab-config.md +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/common.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/core.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/projects.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/configuration/transform.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/constants.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/commits.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/merge_requests.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/pipelines.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/projects.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/python_gitlab.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/gitlab/variables.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/filter.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/lists/projects.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/output.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/abstract_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/application/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/application/application_settings_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/defining_keys.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_badges_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_hooks_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_labels_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_members_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_protected_branches_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_push_rules_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_saml_links_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_settings_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/group/group_variables_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/multiple_entities_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/badges_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/branches_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/files_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/hooks_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/integrations_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/members_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_labels_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_security_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_settings_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/project_variables_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/protected_environments_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/remote_mirrors_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/resource_groups_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/schedules_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/project/tags_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/badges_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/branch_protection.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/decorators.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/difference_logger.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/labels_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/processors/util/variables_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/gitlabform/run.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/mkdocs.yml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/prek.toml +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/conftest.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_branches.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_branches_users_case_insensitive.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_ldap_links.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_protected_branches.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_push_rules.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_saml_links.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_group_variables.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_merge_request_approval_rules.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_merge_request_approvals_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_protected_environments.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_push_rules.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/premium/test_tags.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_application_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_archive_project.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_badges.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_branches.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_deploy_keys.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_deploy_keys_all_projects.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_files.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_files_templates.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_avatar.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_badges.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_hooks.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_labels.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_members_case_insensitive.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_members_groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_members_users.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_group_variables.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_hooks.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_integrations.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_job_token_scope.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_members.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_members_add_group.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_members_enforce.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_avatar.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_group_members_case_insensitive.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_labels.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_members_case_insensitve.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_project_variables.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_remote_mirrors.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_resource_groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_running.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_scheduled_for_deletion_project.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_schedules.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_tags.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_token_from_config.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_transfer_project.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/standard/test_wildcard_patterns.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_group_members.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_group_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_members.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_project_security_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/acceptance/ultimate/test_project_settings.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_case_sensitivity.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_inheritance_break_projects_and_groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_inheritance_break_subgroups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_inheritance_break_validation.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_projects_and_groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_skip_groups_skip_projects.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_subgroups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_wildcard_patterns.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/test_yaml_version.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_access_level_transformer.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_group_transformer.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_implicit_name_transformer.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_user_and_group_transformers.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/configuration/transform/test_user_transformer.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/gitlab/test_core.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/gitlab/test_groups.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/gitlab/test_python_gitlab.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/__init__.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_abstract_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_abstract_processors.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_branches_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_deploy_keys_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_difference_logger.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_files_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_ldap_links_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_members_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_protected_branches_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_group_saml_links_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_protected_environments_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_schedules_processor_extended_cron_pattern.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/processors/test_util_badges_processor.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_access_levels.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_non_empty_configs_provider.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_output.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_parse_args.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_projects_provider.py +0 -0
- {gitlabform-6.3.0 → gitlabform-6.3.1}/tests/unit/test_show_summary.py +0 -0
- {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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
81
|
+
"zensical==0.0.65",
|
|
82
82
|
"pygments==2.21.0",
|
|
83
|
-
"pymdown-extensions==12.
|
|
83
|
+
"pymdown-extensions==12.1",
|
|
84
84
|
]
|
|
85
85
|
# Tools required for building and verifying releases.
|
|
86
86
|
release = [
|
|
@@ -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
|