gitlabform 5.5.3__tar.gz → 5.5.5__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-5.5.3 → gitlabform-5.5.5}/.github/workflows/_releases.yml +1 -7
- {gitlabform-5.5.3 → gitlabform-5.5.5}/PKG-INFO +4 -4
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/changelog.md +18 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/files.md +43 -1
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/files_processor.py +145 -108
- {gitlabform-5.5.3 → gitlabform-5.5.5}/pyproject.toml +10 -10
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tbump.toml +1 -1
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_branches.py +52 -1
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_files.py +176 -0
- gitlabform-5.5.5/tests/unit/processors/test_files_processor.py +312 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/uv.lock +169 -169
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.coveragerc +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.dockerignore +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.git-blame-ignore-revs +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/CODEOWNERS +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/ISSUE_TEMPLATE/question-or-other-issue.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/actions/setup-uv-local/README.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/actions/setup-uv-local/action.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/dependabot.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/_main.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/docs.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/linters.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/pr_on_fork.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/pr_on_main_repo.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/prs.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/tests-premium.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/tests-standard.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.github/workflows/tests-ultimate.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.gitignore +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.lgtm.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.mypy.ini +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.overrides/gitlabform-logo-favicon.png +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.overrides/gitlabform-logo-favicon.svg +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/.python-version +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/CONTRIBUTING.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/Dockerfile +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/LICENSE +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/README.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/codecov.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/common.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/docs.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/env.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/gitlab/await-healthy.sh +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/gitlab/gitlab.rb +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/gitlab/healthcheck-and-setup.sh +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/gitlab/run_gitlab_in_docker.sh +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/gitlab/tests.Dockerfile +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/infra.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/main.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/qa.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/dev/release.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/automation.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/contrib/coding_guidelines.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/contrib/implementation_design.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/contrib/index.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/contrib/local_development.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/contrib/releases.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/contrib/workflows.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/features.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/egnyte-logo.svg +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/elastic-path-logo.svg +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/gitlabform-logo-square.png +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/gitlabform-logo.png +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/gitlabform-logo.svg +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/group-ldap-links-provider.png +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/liquidlight-logo.svg +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/roche-logo.png +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/images/stroeer-online-marketing-logo.svg +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/index.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/installation.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/archive_unarchive.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/avatar.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/badges.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/ci_cd_variables.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/deploy_keys.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/group_ldap_links.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/group_saml_links.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/index.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/integrations.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/job_token_scope.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/labels.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/members.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/merge_requests.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/pipeline_schedules.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/project_security_settings.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/project_transfer.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/protected_branches.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/protected_environments.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/push_mirrors.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/push_rules.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/resource_groups.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/settings.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/tags_protection.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/reference/webhooks.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/requirements.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/running.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/similar_apps.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/docs/upgrade.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlab-config/config.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlab-config/gitlab-config.md +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/configuration/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/configuration/common.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/configuration/core.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/configuration/groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/configuration/projects.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/configuration/transform.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/constants.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/commits.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/core.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/group_badges.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/group_ldap_links.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/merge_requests.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/pipelines.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/project_badges.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/project_deploy_keys.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/project_merge_requests_approvals.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/project_protected_environments.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/projects.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/python_gitlab.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/gitlab/variables.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/lists/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/lists/filter.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/lists/groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/lists/projects.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/output.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/abstract_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/application/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/application/application_settings_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/defining_keys.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_badges_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_hooks_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_labels_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_members_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_protected_branches_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_push_rules_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_saml_links_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_settings_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/group/group_variables_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/multiple_entities_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/badges_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/branches_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/hooks_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/integrations_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/members_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/merge_requests_approval_rules.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/project_labels_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/project_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/project_security_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/project_settings_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/project_variables_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/remote_mirrors_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/resource_groups_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/schedules_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/project/tags_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/shared/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/shared/protected_environments_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/util/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/util/branch_protection.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/util/decorators.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/util/difference_logger.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/util/labels_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/processors/util/variables_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/run.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/gitlabform/util.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/mkdocs.yml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/prek.toml +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/conftest.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_branches.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_branches_users_case_insensitive.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_group_ldap_links.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_group_protected_branches.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_group_push_rules.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_group_saml_links.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_group_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_group_variables.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_merge_request_approval_rules.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_merge_request_approvals_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_protected_environments.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_push_rules.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/premium/test_tags.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_application_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_archive_project.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_badges.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_deploy_keys.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_deploy_keys_all_projects.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_files_templates.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_avatar.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_badges.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_hooks.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_labels.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_members_case_insensitive.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_members_groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_members_users.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_group_variables.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_hooks.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_integrations.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_job_token_scope.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_members.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_members_add_group.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_members_enforce.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_project_avatar.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_project_group_members_case_insensitive.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_project_labels.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_project_members_case_insensitve.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_project_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_project_variables.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_remote_mirrors.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_resource_groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_running.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_scheduled_for_deletion_project.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_schedules.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_tags.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_token_from_config.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/standard/test_transfer_project.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/ultimate/test_group_members.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/ultimate/test_group_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/ultimate/test_members.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/ultimate/test_project_security_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/acceptance/ultimate/test_project_settings.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_case_sensitivity.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_inheritance_break_projects_and_groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_inheritance_break_subgroups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_inheritance_break_validation.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_projects_and_groups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_skip_groups_skip_projects.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_subgroups.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/test_yaml_version.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/transform/test_access_level_transformer.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/transform/test_group_transformer.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/transform/test_implicit_name_transformer.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/transform/test_user_and_group_transformers.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/configuration/transform/test_user_transformer.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/gitlab/test_core.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/gitlab/test_python_gitlab.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/__init__.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/test_abstract_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/test_abstract_processors.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/test_branches_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/test_difference_logger.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/test_group_protected_branches_processor.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/processors/test_schedules_processor_extended_cron_pattern.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/test_access_levels.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/test_non_empty_configs_provider.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/test_parse_args.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/test_projects_provider.py +0 -0
- {gitlabform-5.5.3 → gitlabform-5.5.5}/tests/unit/test_utils.py +0 -0
|
@@ -119,15 +119,8 @@ jobs:
|
|
|
119
119
|
runs-on: ubuntu-latest
|
|
120
120
|
steps:
|
|
121
121
|
- uses: actions/checkout@v6
|
|
122
|
-
- name: Configure uv environment
|
|
123
|
-
uses: ./.github/actions/setup-uv-local
|
|
124
122
|
- name: Get the version from the tag
|
|
125
123
|
run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV
|
|
126
|
-
- name: Wait for PyPI release
|
|
127
|
-
run: |
|
|
128
|
-
uv pip install gitlabform==${{ env.VERSION }} --dry-run --system > /dev/null
|
|
129
|
-
while [ $? -ne 0 ]; do echo "Waiting for gitlabform==${{ env.VERSION }} to be available on PyPI..."; sleep 10; uv pip install gitlabform==${{ env.VERSION }} --dry-run --system > /dev/null ; done
|
|
130
|
-
shell: bash {0}
|
|
131
124
|
- name: Docker metadata
|
|
132
125
|
id: metadata
|
|
133
126
|
uses: docker/metadata-action@v6
|
|
@@ -152,6 +145,7 @@ jobs:
|
|
|
152
145
|
username: ${{ github.repository_owner }}
|
|
153
146
|
# This token is provided by Actions, you do not need to create your own token
|
|
154
147
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
148
|
+
# Docker image will use UV internally and builds the image from the Codebase at the current tag, rather than downloding from PyPi
|
|
155
149
|
- name: Publish image to registries
|
|
156
150
|
uses: docker/build-push-action@v7
|
|
157
151
|
with:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version: 5.5.
|
|
3
|
+
Version: 5.5.5
|
|
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.5.20
|
|
23
23
|
Requires-Dist: cli-ui==0.19.0
|
|
24
24
|
Requires-Dist: ez-yaml==1.2.0
|
|
25
25
|
Requires-Dist: jinja2==3.1.6
|
|
@@ -27,8 +27,8 @@ Requires-Dist: luddite==1.0.4
|
|
|
27
27
|
Requires-Dist: markupsafe==3.0.3
|
|
28
28
|
Requires-Dist: mergedeep==1.3.4
|
|
29
29
|
Requires-Dist: packaging==26.2
|
|
30
|
-
Requires-Dist: python-gitlab[graphql]==8.
|
|
31
|
-
Requires-Dist: requests==2.
|
|
30
|
+
Requires-Dist: python-gitlab[graphql]==8.4.0
|
|
31
|
+
Requires-Dist: requests==2.34.2
|
|
32
32
|
Requires-Dist: rich==15.0.0
|
|
33
33
|
Requires-Dist: ruamel-yaml==0.17.21
|
|
34
34
|
Requires-Dist: yamlpath==3.8.2
|
|
@@ -5,6 +5,24 @@ This changelog follows industry-standard best practices. Each release includes t
|
|
|
5
5
|
For details on how to migrate between major versions, please refer to the [upgrade guide](upgrade.md), which contains important instructions for breaking changes.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
|
+
## 5.5.5
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* allow editing and creation of files on wildcard protected branches [#1282](https://github.com/gitlabform/gitlabform/pull/1282). ([timknight01](https://github.com/TimKnight01) & [rickbrouwer](https://github.com/rickbrouwer))
|
|
13
|
+
|
|
14
|
+
### Dependencies
|
|
15
|
+
|
|
16
|
+
* Update various dependencies to newer versions.
|
|
17
|
+
|
|
18
|
+
Thanks to all the contributors of this release!
|
|
19
|
+
|
|
20
|
+
## 5.5.4
|
|
21
|
+
|
|
22
|
+
### Build
|
|
23
|
+
|
|
24
|
+
* Simplify publishing to GHCR to remove direct need to check PyPi before building Docker image. ([timknight01](https://github.com/TimKnight01))
|
|
25
|
+
|
|
8
26
|
|
|
9
27
|
## 5.5.3
|
|
10
28
|
|
|
@@ -8,7 +8,7 @@ Each key in this section is a path to a file in the repo and the values are dict
|
|
|
8
8
|
|
|
9
9
|
* `overwrite` - if set to `false` and the file already exists, but has a different content, then it is not changed; default is `true`,
|
|
10
10
|
* `skip_ci` - if set to `true` then the changes to a given file will be done with commits that will not trigger the CI pipeline; default is `false`,
|
|
11
|
-
* `branches` - can be a single string `all`, string `protected` or an array of branch names,
|
|
11
|
+
* `branches` - can be a single string `all`, string `protected` (all protected branches, with wildcard-protected rules expanded to matching branches), or an array of branch names where `*` can be used to match any sequence of characters (e.g. `bugfix/*`, `*release*`),
|
|
12
12
|
* `only_first_branch` - if set to `true` then only the first branch from the list above that exists will be processed (unless you pass `--strict` as cli parameter to the app - then it will fail when trying to process a non-existent branch),
|
|
13
13
|
* `commit_message` - set this to a custom commit message that will be used by the app; optional,
|
|
14
14
|
* `content` - the literal contents that should be put into the target file; use this or `file`,
|
|
@@ -94,3 +94,45 @@ projects_and_groups:
|
|
|
94
94
|
only_first_branch: true
|
|
95
95
|
skip_ci: true
|
|
96
96
|
```
|
|
97
|
+
|
|
98
|
+
Example 5 - adding a README to all branches with "gitlab" in their name:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
projects_and_groups:
|
|
102
|
+
group_1/project_1:
|
|
103
|
+
files:
|
|
104
|
+
"README.md":
|
|
105
|
+
overwrite: false
|
|
106
|
+
branches:
|
|
107
|
+
- "*gitlab*"
|
|
108
|
+
skip_ci: true
|
|
109
|
+
content: |
|
|
110
|
+
This is a default README. Please replace it with a proper one!
|
|
111
|
+
commit_message: Set default README
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Example 6 - adding a README to protected branches, including protected branches defined with wildcards (e.g. all branches with "bugfix/" in their name are protected and will have the file added):
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
projects_and_groups:
|
|
118
|
+
group_1/project_1:
|
|
119
|
+
branches:
|
|
120
|
+
main:
|
|
121
|
+
allow_force_push: false
|
|
122
|
+
code_owner_approval_required: true
|
|
123
|
+
merge_access_level: developer
|
|
124
|
+
protected: true
|
|
125
|
+
bugfix/*:
|
|
126
|
+
allow_force_push: true
|
|
127
|
+
code_owner_approval_required: false
|
|
128
|
+
merge_access_level: developer
|
|
129
|
+
protected: true
|
|
130
|
+
files:
|
|
131
|
+
"README.md":
|
|
132
|
+
overwrite: false
|
|
133
|
+
branches: protected
|
|
134
|
+
skip_ci: true
|
|
135
|
+
content: |
|
|
136
|
+
This is a protected branch README!
|
|
137
|
+
commit_message: Set protected branch README
|
|
138
|
+
```
|
|
@@ -4,10 +4,9 @@ import sys
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
6
|
from logging import debug, info, warning, critical
|
|
7
|
-
from typing import List
|
|
8
7
|
|
|
9
8
|
from jinja2 import Environment, FileSystemLoader
|
|
10
|
-
from gitlab import GitlabGetError, GitlabUpdateError
|
|
9
|
+
from gitlab import GitlabGetError, GitlabUpdateError, GitlabListError
|
|
11
10
|
from gitlab.v4.objects import Project, ProjectFile, ProjectBranch
|
|
12
11
|
from gitlab.base import RESTObject
|
|
13
12
|
|
|
@@ -35,27 +34,20 @@ class FilesProcessor(AbstractProcessor):
|
|
|
35
34
|
continue
|
|
36
35
|
|
|
37
36
|
config_target_ref = configuration["files"][file]["branches"]
|
|
38
|
-
branches_to_update:
|
|
39
|
-
|
|
40
|
-
if
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
branches_to_update: list[ProjectBranch] = []
|
|
38
|
+
|
|
39
|
+
if config_target_ref == "all":
|
|
40
|
+
# Get all Branches in the Project
|
|
41
|
+
branches_to_update.extend(project.branches.list(get_all=True, lazy=True))
|
|
42
|
+
elif config_target_ref == "protected":
|
|
43
|
+
# Get all Protected Branch definitions -> this could return wildcard branch names
|
|
44
|
+
protected_branches = project.protectedbranches.list(get_all=True, lazy=True)
|
|
45
|
+
for protected_branch in protected_branches:
|
|
46
|
+
self.append_branches_matching_ref(branches_to_update, file, project, protected_branch.name)
|
|
47
47
|
elif isinstance(config_target_ref, list):
|
|
48
|
-
#
|
|
49
|
-
for
|
|
50
|
-
|
|
51
|
-
branches_to_update.append(project.branches.get(branch_name))
|
|
52
|
-
except GitlabGetError:
|
|
53
|
-
message = f"! Branch '{branch_name}' not found, not processing file '{file}' in it"
|
|
54
|
-
if self.strict:
|
|
55
|
-
critical(message)
|
|
56
|
-
sys.exit(EXIT_INVALID_INPUT)
|
|
57
|
-
else:
|
|
58
|
-
warning(message)
|
|
48
|
+
# List of specific branch refs to update -> this could contain wildcard branch names
|
|
49
|
+
for ref in config_target_ref:
|
|
50
|
+
self.append_branches_matching_ref(branches_to_update, file, project, ref)
|
|
59
51
|
|
|
60
52
|
debug(
|
|
61
53
|
"File '%s' to be updated in '%s' branche(s)",
|
|
@@ -63,105 +55,150 @@ class FilesProcessor(AbstractProcessor):
|
|
|
63
55
|
len(branches_to_update),
|
|
64
56
|
)
|
|
65
57
|
|
|
66
|
-
for
|
|
67
|
-
|
|
58
|
+
for branch_to_update in branches_to_update:
|
|
59
|
+
process_only_first: bool = configuration.get("files|" + file + "|only_first_branch", False)
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
61
|
+
self.process_branch(branch_to_update, configuration, file, project, project_and_group)
|
|
62
|
+
|
|
63
|
+
if process_only_first:
|
|
64
|
+
info("Skipping other branches for this file, as configured by only_first_branch.")
|
|
65
|
+
break
|
|
66
|
+
|
|
67
|
+
def append_branches_matching_ref(self, branches_to_update: list[ProjectBranch], file, project: Project, ref: str):
|
|
68
|
+
|
|
69
|
+
if self.branch_processor.branch_name_contains_supported_wildcard(ref):
|
|
70
|
+
try:
|
|
71
|
+
# GitLab's branches API expects an RE2 regex
|
|
72
|
+
regex_ref = "^" + re.escape(ref).replace(r"\*", ".*") + "$"
|
|
73
|
+
# sorted for deterministic only_first_branch
|
|
74
|
+
wildcard_branches = sorted(
|
|
75
|
+
project.branches.list(get_all=True, regex=regex_ref),
|
|
76
|
+
key=lambda b: b.name,
|
|
77
|
+
)
|
|
78
|
+
for wildcard_branch in wildcard_branches:
|
|
79
|
+
branch_id = wildcard_branch.get_id()
|
|
80
|
+
if branch_id:
|
|
81
|
+
branches_to_update.append(wildcard_branch)
|
|
82
|
+
except GitlabListError:
|
|
83
|
+
message = f"! Could not list branches using {ref}, not processing file '{file}' on them"
|
|
84
|
+
if self.strict:
|
|
85
|
+
critical(message)
|
|
74
86
|
sys.exit(EXIT_INVALID_INPUT)
|
|
87
|
+
else:
|
|
88
|
+
warning(message)
|
|
89
|
+
else:
|
|
90
|
+
try:
|
|
91
|
+
branches_to_update.append(project.branches.get(ref))
|
|
92
|
+
except GitlabGetError:
|
|
93
|
+
message = f"! Branch '{ref}' not found, not processing file '{file}' in it"
|
|
94
|
+
if self.strict:
|
|
95
|
+
critical(message)
|
|
96
|
+
sys.exit(EXIT_INVALID_INPUT)
|
|
97
|
+
else:
|
|
98
|
+
warning(message)
|
|
75
99
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
def process_branch(
|
|
101
|
+
self,
|
|
102
|
+
branch: ProjectBranch,
|
|
103
|
+
configuration: dict,
|
|
104
|
+
file: str,
|
|
105
|
+
project: Project,
|
|
106
|
+
project_and_group: str,
|
|
107
|
+
):
|
|
108
|
+
info(f"Processing file '{file}' in branch '{branch.name}'")
|
|
109
|
+
|
|
110
|
+
if configuration.get("files|" + file + "|content") and configuration.get("files|" + file + "|file"):
|
|
111
|
+
critical(
|
|
112
|
+
f"File '{file}' in '{project_and_group}' has both `content` and `file` set - "
|
|
113
|
+
"use only one of these keys."
|
|
114
|
+
)
|
|
115
|
+
sys.exit(EXIT_INVALID_INPUT)
|
|
116
|
+
|
|
117
|
+
if configuration.get("files|" + file + "|delete"):
|
|
118
|
+
try:
|
|
119
|
+
file_to_delete: ProjectFile = project.files.get(file_path=file, ref=branch.name)
|
|
120
|
+
debug("Deleting file '%s' in branch '%s'", file, branch.name)
|
|
121
|
+
self.modify_file_dealing_with_branch_protection(
|
|
122
|
+
project,
|
|
123
|
+
branch,
|
|
124
|
+
file_to_delete,
|
|
125
|
+
"delete",
|
|
126
|
+
configuration,
|
|
127
|
+
)
|
|
128
|
+
except GitlabGetError:
|
|
129
|
+
debug(
|
|
130
|
+
"Not deleting file '%s' in branch '%s' (already doesn't exist)",
|
|
131
|
+
file,
|
|
132
|
+
branch.name,
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
# change or create file
|
|
136
|
+
|
|
137
|
+
if configuration.get("files|" + file + "|content"):
|
|
138
|
+
new_content = configuration.get("files|" + file + "|content")
|
|
139
|
+
else:
|
|
140
|
+
path_in_config = Path(str(configuration.get("files|" + file + "|file")))
|
|
141
|
+
if path_in_config.is_absolute():
|
|
142
|
+
effective_path = path_in_config
|
|
143
|
+
else:
|
|
144
|
+
# relative paths are relative to config file location
|
|
145
|
+
effective_path = Path(os.path.join(self.config.config_dir, str(path_in_config)))
|
|
146
|
+
new_content = effective_path.read_text()
|
|
147
|
+
|
|
148
|
+
# templating is documented to be enabled by default,
|
|
149
|
+
# see https://gitlabform.github.io/gitlabform/reference/files/#files
|
|
150
|
+
templating_enabled = True
|
|
151
|
+
|
|
152
|
+
if configuration.get("files|" + file + "|template", templating_enabled):
|
|
153
|
+
new_content = self.get_file_content_as_template(
|
|
154
|
+
new_content,
|
|
155
|
+
project_and_group,
|
|
156
|
+
**configuration.get("files|" + file + "|jinja_env", dict()),
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
# Returns base64 encoded content: https://python-gitlab.readthedocs.io/en/stable/gl_objects/projects.html#project-files
|
|
161
|
+
repo_file: ProjectFile = project.files.get(file_path=file, ref=branch.name)
|
|
162
|
+
decoded_file: bytes = repo_file.decode()
|
|
163
|
+
current_content: str = decoded_file.decode("utf-8")
|
|
164
|
+
|
|
165
|
+
if current_content != new_content:
|
|
166
|
+
if configuration.get("files|" + file + "|overwrite"):
|
|
88
167
|
debug(
|
|
89
|
-
"
|
|
168
|
+
"Changing file '%s' in branch '%s'",
|
|
90
169
|
file,
|
|
91
170
|
branch.name,
|
|
92
171
|
)
|
|
93
|
-
else:
|
|
94
|
-
# change or create file
|
|
95
|
-
|
|
96
|
-
if configuration.get("files|" + file + "|content"):
|
|
97
|
-
new_content = configuration.get("files|" + file + "|content")
|
|
98
|
-
else:
|
|
99
|
-
path_in_config = Path(str(configuration.get("files|" + file + "|file")))
|
|
100
|
-
if path_in_config.is_absolute():
|
|
101
|
-
effective_path = path_in_config
|
|
102
|
-
else:
|
|
103
|
-
# relative paths are relative to config file location
|
|
104
|
-
effective_path = Path(os.path.join(self.config.config_dir, str(path_in_config)))
|
|
105
|
-
new_content = effective_path.read_text()
|
|
106
|
-
|
|
107
|
-
# templating is documented to be enabled by default,
|
|
108
|
-
# see https://gitlabform.github.io/gitlabform/reference/files/#files
|
|
109
|
-
templating_enabled = True
|
|
110
|
-
|
|
111
|
-
if configuration.get("files|" + file + "|template", templating_enabled):
|
|
112
|
-
new_content = self.get_file_content_as_template(
|
|
113
|
-
new_content,
|
|
114
|
-
project_and_group,
|
|
115
|
-
**configuration.get("files|" + file + "|jinja_env", dict()),
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
try:
|
|
119
|
-
# Returns base64 encoded content: https://python-gitlab.readthedocs.io/en/stable/gl_objects/projects.html#project-files
|
|
120
|
-
repo_file: ProjectFile = project.files.get(file_path=file, ref=branch.name)
|
|
121
|
-
decoded_file: bytes = repo_file.decode()
|
|
122
|
-
current_content: str = decoded_file.decode("utf-8")
|
|
123
|
-
|
|
124
|
-
if current_content != new_content:
|
|
125
|
-
if configuration.get("files|" + file + "|overwrite"):
|
|
126
|
-
debug(
|
|
127
|
-
"Changing file '%s' in branch '%s'",
|
|
128
|
-
file,
|
|
129
|
-
branch.name,
|
|
130
|
-
)
|
|
131
|
-
self.modify_file_dealing_with_branch_protection(
|
|
132
|
-
project,
|
|
133
|
-
branch,
|
|
134
|
-
repo_file,
|
|
135
|
-
"modify",
|
|
136
|
-
configuration,
|
|
137
|
-
new_content,
|
|
138
|
-
)
|
|
139
|
-
else:
|
|
140
|
-
debug(
|
|
141
|
-
"Not changing file '%s' in branch '%s' - overwrite flag not set.",
|
|
142
|
-
file,
|
|
143
|
-
branch.name,
|
|
144
|
-
)
|
|
145
|
-
else:
|
|
146
|
-
debug(
|
|
147
|
-
"Not changing file '%s' in branch '%s' - it's content is already" " as provided)",
|
|
148
|
-
file,
|
|
149
|
-
branch.name,
|
|
150
|
-
)
|
|
151
|
-
except GitlabGetError:
|
|
152
|
-
debug("Creating file '%s' in branch '%s'", file, branch.name)
|
|
153
172
|
self.modify_file_dealing_with_branch_protection(
|
|
154
173
|
project,
|
|
155
174
|
branch,
|
|
156
|
-
|
|
157
|
-
"
|
|
175
|
+
repo_file,
|
|
176
|
+
"modify",
|
|
158
177
|
configuration,
|
|
159
178
|
new_content,
|
|
160
179
|
)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
180
|
+
else:
|
|
181
|
+
debug(
|
|
182
|
+
"Not changing file '%s' in branch '%s' - overwrite flag not set.",
|
|
183
|
+
file,
|
|
184
|
+
branch.name,
|
|
185
|
+
)
|
|
186
|
+
else:
|
|
187
|
+
debug(
|
|
188
|
+
"Not changing file '%s' in branch '%s' - it's content is already" " as provided)",
|
|
189
|
+
file,
|
|
190
|
+
branch.name,
|
|
191
|
+
)
|
|
192
|
+
except GitlabGetError:
|
|
193
|
+
debug("Creating file '%s' in branch '%s'", file, branch.name)
|
|
194
|
+
self.modify_file_dealing_with_branch_protection(
|
|
195
|
+
project,
|
|
196
|
+
branch,
|
|
197
|
+
file,
|
|
198
|
+
"add",
|
|
199
|
+
configuration,
|
|
200
|
+
new_content,
|
|
201
|
+
)
|
|
165
202
|
|
|
166
203
|
def modify_file_dealing_with_branch_protection(
|
|
167
204
|
self,
|
|
@@ -10,7 +10,7 @@ packages = ["gitlabform"]
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "gitlabform"
|
|
13
|
-
version = "5.5.
|
|
13
|
+
version = "5.5.5"
|
|
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.5.20",
|
|
35
35
|
"cli-ui==0.19.0",
|
|
36
36
|
# ez_yaml >1.2.0 changes imports and also uses ruamel.yaml tied to 1.2 so wouldn't support "yes" as True
|
|
37
37
|
"ez-yaml==1.2.0",
|
|
@@ -40,8 +40,8 @@ dependencies = [
|
|
|
40
40
|
"markupsafe==3.0.3",
|
|
41
41
|
"mergedeep==1.3.4",
|
|
42
42
|
"packaging==26.2",
|
|
43
|
-
"python-gitlab[graphql]==8.
|
|
44
|
-
"requests==2.
|
|
43
|
+
"python-gitlab[graphql]==8.4.0",
|
|
44
|
+
"requests==2.34.2",
|
|
45
45
|
"rich==15.0.0",
|
|
46
46
|
# yamlpath and ruamel and tightly coupled, currently 0.19.1 of ruamel and 3.9.0 of yamlpath break support for
|
|
47
47
|
# yaml 1.1 "yes" -> True conversion. If we want to upgrade we'd need to make a breaking-change and drop support for
|
|
@@ -58,27 +58,27 @@ dev = [
|
|
|
58
58
|
{ include-group = "lint" },
|
|
59
59
|
{ include-group = "docs" },
|
|
60
60
|
{ include-group = "release" },
|
|
61
|
-
"commitizen==4.16.
|
|
62
|
-
"prek==0.4.
|
|
61
|
+
"commitizen==4.16.3",
|
|
62
|
+
"prek==0.4.3",
|
|
63
63
|
]
|
|
64
64
|
# Minimum set of dependencies required to execute the test suite.
|
|
65
65
|
test = [
|
|
66
|
-
"coverage==7.14.
|
|
66
|
+
"coverage==7.14.1",
|
|
67
67
|
"cryptography==48.0.0",
|
|
68
68
|
"deepdiff==9.1.0",
|
|
69
69
|
"pytest==9.0.3",
|
|
70
70
|
"pytest-cov==7.1.0",
|
|
71
|
-
"pytest-rerunfailures==16.
|
|
71
|
+
"pytest-rerunfailures==16.3",
|
|
72
72
|
"xkcdpass==1.30.0",
|
|
73
73
|
]
|
|
74
74
|
# Static analysis and formatting tools.
|
|
75
75
|
lint = [
|
|
76
76
|
"bandit==1.9.4",
|
|
77
|
-
"black==26.5.
|
|
77
|
+
"black==26.5.1",
|
|
78
78
|
"codespell==2.4.2",
|
|
79
79
|
"mypy==2.1.0",
|
|
80
80
|
"mypy-extensions==1.1.0",
|
|
81
|
-
"ruff==0.15.
|
|
81
|
+
"ruff==0.15.15",
|
|
82
82
|
"types-requests==2.33.0.20260518",
|
|
83
83
|
]
|
|
84
84
|
# Documentation generation stack.
|
|
@@ -4,7 +4,7 @@ import time
|
|
|
4
4
|
from gitlab import GitlabGetError
|
|
5
5
|
|
|
6
6
|
from gitlabform.gitlab import AccessLevel
|
|
7
|
-
from tests.acceptance import get_only_branch_access_levels, run_gitlabform
|
|
7
|
+
from tests.acceptance import get_only_branch_access_levels, run_gitlabform, get_random_name
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@pytest.mark.ce
|
|
@@ -401,3 +401,54 @@ class TestBranches:
|
|
|
401
401
|
assert other_branch_unprotect_access_level is AccessLevel.MAINTAINER.value
|
|
402
402
|
else:
|
|
403
403
|
assert other_branch_unprotect_access_level is None
|
|
404
|
+
|
|
405
|
+
def test__can_protect_branches_with_wildcard(self, project_for_function, branch_for_function):
|
|
406
|
+
# Setup Test
|
|
407
|
+
|
|
408
|
+
### Test-config:
|
|
409
|
+
set_file_protected_branches = f"""
|
|
410
|
+
protected branch: &protected_branch
|
|
411
|
+
allow_force_push: false
|
|
412
|
+
code_owner_approval_required: true
|
|
413
|
+
merge_access_level: developer
|
|
414
|
+
protected: true
|
|
415
|
+
push_access_level: maintainer
|
|
416
|
+
unprotect_access_level: maintainer
|
|
417
|
+
|
|
418
|
+
projects_and_groups:
|
|
419
|
+
{project_for_function.path_with_namespace}:
|
|
420
|
+
branches:
|
|
421
|
+
main: *protected_branch
|
|
422
|
+
bugfix/*: *protected_branch
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
### Make sure "main" exists on project
|
|
426
|
+
main_branch_name: str = "main"
|
|
427
|
+
assert project_for_function.branches.get(main_branch_name) is not None
|
|
428
|
+
|
|
429
|
+
### Make sure "branch_for_function" exists on project
|
|
430
|
+
assert project_for_function.branches.get(branch_for_function) is not None
|
|
431
|
+
|
|
432
|
+
### Add a "bugfix/some-branch" and a "bugfix/other-fix" to project
|
|
433
|
+
bug_fix_branch_name_1 = f"bugfix/{get_random_name("branch")}"
|
|
434
|
+
bug_fix_branch_name_2 = f"bugfix/{get_random_name("branch")}"
|
|
435
|
+
|
|
436
|
+
project_for_function.branches.create({"branch": bug_fix_branch_name_1, "ref": "main"})
|
|
437
|
+
project_for_function.branches.create({"branch": bug_fix_branch_name_2, "ref": "main"})
|
|
438
|
+
|
|
439
|
+
time.sleep(5)
|
|
440
|
+
# Wait a bit to make sure GitLab has asynchronously created the branches before we run GitLabForm
|
|
441
|
+
|
|
442
|
+
# Run Test
|
|
443
|
+
run_gitlabform(set_file_protected_branches, project_for_function.path_with_namespace)
|
|
444
|
+
|
|
445
|
+
# Assert correct changes are applied
|
|
446
|
+
### Check Main branch is protected
|
|
447
|
+
assert project_for_function.branches.get(main_branch_name).protected is True
|
|
448
|
+
|
|
449
|
+
### Check both Bugfix branches are protected
|
|
450
|
+
assert project_for_function.branches.get(bug_fix_branch_name_1).protected is True
|
|
451
|
+
assert project_for_function.branches.get(bug_fix_branch_name_2).protected is True
|
|
452
|
+
|
|
453
|
+
### Check branch_for_function is not protected
|
|
454
|
+
assert project_for_function.branches.get(branch_for_function).protected is False
|