gitlabform 5.5.6__tar.gz → 6.0.0__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.6 → gitlabform-6.0.0}/.github/workflows/_releases.yml +2 -2
- {gitlabform-5.5.6 → gitlabform-6.0.0}/PKG-INFO +3 -4
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/changelog.md +16 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/upgrade.md +19 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/__init__.py +21 -14
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/configuration/core.py +0 -4
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/configuration/transform.py +12 -11
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/output.py +2 -3
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/__init__.py +2 -2
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_variables_processor.py +19 -13
- gitlabform-6.0.0/gitlabform/util.py +47 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/pyproject.toml +3 -9
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tbump.toml +1 -1
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_files_templates.py +1 -1
- gitlabform-6.0.0/tests/unit/configuration/test_yaml_version.py +63 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/transform/test_access_level_transformer.py +3 -11
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/transform/test_group_transformer.py +1 -7
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/transform/test_implicit_name_transformer.py +2 -3
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/transform/test_user_and_group_transformers.py +1 -19
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/transform/test_user_transformer.py +6 -17
- {gitlabform-5.5.6 → gitlabform-6.0.0}/uv.lock +9 -127
- gitlabform-5.5.6/gitlabform/util.py +0 -7
- gitlabform-5.5.6/tests/unit/configuration/test_yaml_version.py +0 -36
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.coveragerc +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.dockerignore +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.git-blame-ignore-revs +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/CODEOWNERS +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/ISSUE_TEMPLATE/question-or-other-issue.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/actions/setup-uv-local/README.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/actions/setup-uv-local/action.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/dependabot.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/_main.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/build.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/pr-ci-workflow.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/prs-entrypoint-forks.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/prs-entrypoint-main.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/static-analysis.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/tests-acceptance.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.github/workflows/tests-unit.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.gitignore +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.lgtm.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.mypy.ini +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.overrides/gitlabform-logo-favicon.png +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.overrides/gitlabform-logo-favicon.svg +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/.python-version +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/CONTRIBUTING.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/Dockerfile +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/LICENSE +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/README.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/codecov.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/common.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/docker.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/docs.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/env.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/gitlab/await-healthy.sh +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/gitlab/gitlab.rb +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/gitlab/healthcheck-and-setup.sh +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/gitlab/run_gitlab_in_docker.sh +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/gitlab/tests.Dockerfile +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/infra.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/main.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/package.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/qa.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/dev/release.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/automation.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/contrib/coding_guidelines.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/contrib/implementation_design.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/contrib/index.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/contrib/local_development.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/contrib/releases.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/contrib/workflows.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/features.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/Opencast-logo.png +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/egnyte-logo.svg +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/elastic-path-logo.svg +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/gitlabform-logo-square.png +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/gitlabform-logo.png +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/gitlabform-logo.svg +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/group-ldap-links-provider.png +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/liquidlight-logo.svg +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/roche-logo.png +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/images/stroeer-online-marketing-logo.svg +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/index.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/installation.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/archive_unarchive.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/avatar.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/badges.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/ci_cd_variables.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/deploy_keys.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/files.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/group_ldap_links.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/group_saml_links.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/index.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/integrations.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/job_token_scope.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/labels.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/members.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/merge_requests.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/pipeline_schedules.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/project_security_settings.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/project_transfer.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/protected_branches.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/protected_environments.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/push_mirrors.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/push_rules.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/resource_groups.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/settings.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/tags_protection.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/reference/webhooks.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/requirements.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/running.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/docs/similar_apps.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlab-config/config.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlab-config/gitlab-config.md +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/configuration/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/configuration/common.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/configuration/groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/configuration/projects.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/constants.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/commits.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/core.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/group_badges.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/group_ldap_links.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/merge_requests.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/pipelines.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/project_badges.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/project_deploy_keys.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/project_merge_requests_approvals.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/project_protected_environments.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/projects.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/python_gitlab.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/gitlab/variables.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/lists/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/lists/filter.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/lists/groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/lists/projects.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/abstract_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/application/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/application/application_settings_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/defining_keys.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_badges_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_hooks_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_labels_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_members_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_protected_branches_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_push_rules_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_saml_links_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_settings_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/group/group_variables_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/multiple_entities_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/badges_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/branches_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/files_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/hooks_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/integrations_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/members_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/merge_requests_approval_rules.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_labels_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_security_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_settings_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/remote_mirrors_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/resource_groups_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/schedules_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/tags_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/shared/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/shared/protected_environments_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/util/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/util/branch_protection.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/util/decorators.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/util/difference_logger.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/util/labels_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/util/variables_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/run.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/mkdocs.yml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/prek.toml +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/conftest.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_branches.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_branches_users_case_insensitive.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_group_ldap_links.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_group_protected_branches.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_group_push_rules.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_group_saml_links.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_group_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_group_variables.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_merge_request_approval_rules.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_merge_request_approvals_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_protected_environments.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_push_rules.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/premium/test_tags.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_application_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_archive_project.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_badges.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_branches.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_deploy_keys.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_deploy_keys_all_projects.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_files.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_avatar.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_badges.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_hooks.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_labels.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_members_case_insensitive.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_members_groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_members_users.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_group_variables.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_hooks.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_integrations.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_job_token_scope.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_members.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_members_add_group.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_members_enforce.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_project_avatar.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_project_group_members_case_insensitive.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_project_labels.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_project_members_case_insensitve.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_project_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_project_variables.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_remote_mirrors.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_resource_groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_running.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_scheduled_for_deletion_project.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_schedules.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_tags.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_token_from_config.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/standard/test_transfer_project.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/ultimate/test_group_members.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/ultimate/test_group_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/ultimate/test_members.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/ultimate/test_project_security_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/acceptance/ultimate/test_project_settings.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_case_sensitivity.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_inheritance_break_projects_and_groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_inheritance_break_subgroups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_inheritance_break_validation.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_projects_and_groups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_skip_groups_skip_projects.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/test_subgroups.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/gitlab/test_core.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/gitlab/test_python_gitlab.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/__init__.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_abstract_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_abstract_processors.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_branches_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_difference_logger.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_files_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_group_protected_branches_processor.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/processors/test_schedules_processor_extended_cron_pattern.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/test_access_levels.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/test_non_empty_configs_provider.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/test_parse_args.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/test_projects_provider.py +0 -0
- {gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/test_utils.py +0 -0
|
@@ -165,12 +165,12 @@ jobs:
|
|
|
165
165
|
uses: actions/checkout@v6
|
|
166
166
|
with:
|
|
167
167
|
ref: ${{ needs.prep-release.outputs.semver_tag }}
|
|
168
|
-
- name: Get the version from the tag
|
|
169
|
-
run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV
|
|
170
168
|
- name: Docker metadata
|
|
171
169
|
id: metadata
|
|
172
170
|
uses: docker/metadata-action@v6
|
|
173
171
|
with:
|
|
172
|
+
# Get the ref and the sha from the checked out context - e.g. semver tag rather than triggering branch
|
|
173
|
+
context: git
|
|
174
174
|
images: |
|
|
175
175
|
ghcr.io/gitlabform/gitlabform
|
|
176
176
|
flavor: |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
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
|
|
@@ -21,7 +21,6 @@ Classifier: Topic :: Software Development :: Version Control :: Git
|
|
|
21
21
|
Requires-Python: >=3.12.0
|
|
22
22
|
Requires-Dist: certifi==2026.5.20
|
|
23
23
|
Requires-Dist: cli-ui==0.19.0
|
|
24
|
-
Requires-Dist: ez-yaml==1.2.0
|
|
25
24
|
Requires-Dist: jinja2==3.1.6
|
|
26
25
|
Requires-Dist: luddite==1.0.4
|
|
27
26
|
Requires-Dist: markupsafe==3.0.3
|
|
@@ -30,8 +29,8 @@ Requires-Dist: packaging==26.2
|
|
|
30
29
|
Requires-Dist: python-gitlab[graphql]==8.4.0
|
|
31
30
|
Requires-Dist: requests==2.34.2
|
|
32
31
|
Requires-Dist: rich==15.0.0
|
|
33
|
-
Requires-Dist: ruamel-yaml==0.
|
|
34
|
-
Requires-Dist: yamlpath==3.
|
|
32
|
+
Requires-Dist: ruamel-yaml==0.19.1
|
|
33
|
+
Requires-Dist: yamlpath==3.9.1
|
|
35
34
|
Description-Content-Type: text/markdown
|
|
36
35
|
|
|
37
36
|
[](https://badge.fury.io/gh/gitlabform%2Fgitlabform)
|
|
@@ -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.0.0
|
|
10
|
+
|
|
11
|
+
### Breaking Changes
|
|
12
|
+
|
|
13
|
+
**Drops default support for YAML 1.1 by upgrading dependency major versions:** [#1309](https://github.com/gitlabform/gitlabform/pull/1309). ([timknight01](https://github.com/TimKnight01))
|
|
14
|
+
* Drops DeepDiff and ez_yaml dependencies
|
|
15
|
+
* Upgrades ruamel.yaml and yamlpath to their latest versions
|
|
16
|
+
|
|
17
|
+
See [upgrade guide](upgrade.md) for important upgrade instructions and migration details.
|
|
18
|
+
|
|
19
|
+
## 5.5.7
|
|
20
|
+
|
|
21
|
+
### Build
|
|
22
|
+
|
|
23
|
+
* Fix an issue where the incorrect `ref` was used in docker/metadata-action preventing publishing to GHCR on a Tag. ([timknight01](https://github.com/TimKnight01))
|
|
24
|
+
|
|
9
25
|
## 5.5.6
|
|
10
26
|
|
|
11
27
|
### Documentation
|
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
Some of these changes between major application versions may affect the effective configuration that would be applied if you run the application. Therefore to do the upgrade safely please follow this procedure.
|
|
4
4
|
|
|
5
|
+
## From 5.\* to 6.\*
|
|
6
|
+
|
|
7
|
+
We have upgraded to new major versions of underlying YAML libraries `ezyaml`, `yamlpath` and `ruamel.yaml`.
|
|
8
|
+
|
|
9
|
+
This results in GitLabForm no longer defaulting to `yaml 1.1` support when parsing YAML configuration files.
|
|
10
|
+
|
|
11
|
+
In order to retain `yaml 1.1` configuration you **must** add the `%YAML` directive to the top of your configuration file, for example:
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
%YAML 1.1
|
|
15
|
+
---
|
|
16
|
+
projects_and_groups:
|
|
17
|
+
some_group/*:
|
|
18
|
+
project_settings:
|
|
19
|
+
foo: yes
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Alternatively update your YAML to be compatible with `yaml 1.2` specification, for example by replacing `yes` with `true` in the above example, and any instances of `no` with `false`.
|
|
23
|
+
|
|
5
24
|
## From 4.\* to 5.\*
|
|
6
25
|
|
|
7
26
|
### Update `config_version`
|
|
@@ -68,8 +68,9 @@ class GitLabForm:
|
|
|
68
68
|
self.only_sections = "all"
|
|
69
69
|
self.exclude_sections = []
|
|
70
70
|
self.recurse_subgroups = recurse_subgroups
|
|
71
|
+
self.log_level = logging.DEBUG
|
|
71
72
|
|
|
72
|
-
self.
|
|
73
|
+
self._configure_logging()
|
|
73
74
|
else:
|
|
74
75
|
# normal mode
|
|
75
76
|
|
|
@@ -94,7 +95,16 @@ class GitLabForm:
|
|
|
94
95
|
self.recurse_subgroups,
|
|
95
96
|
) = self._parse_args()
|
|
96
97
|
|
|
97
|
-
self.
|
|
98
|
+
if self.debug:
|
|
99
|
+
level = logging.DEBUG
|
|
100
|
+
elif self.verbose:
|
|
101
|
+
level = logging.INFO
|
|
102
|
+
else:
|
|
103
|
+
level = logging.WARNING
|
|
104
|
+
|
|
105
|
+
self.log_level = level
|
|
106
|
+
|
|
107
|
+
self._configure_logging()
|
|
98
108
|
|
|
99
109
|
self._show_version(self.skip_version_check)
|
|
100
110
|
if self.just_show_version:
|
|
@@ -108,7 +118,7 @@ class GitLabForm:
|
|
|
108
118
|
|
|
109
119
|
self.application_processors = ApplicationProcessors(self.gitlab, self.configuration, self.strict)
|
|
110
120
|
self.group_processors = GroupProcessors(self.gitlab, self.configuration, self.strict)
|
|
111
|
-
self.project_processors = ProjectProcessors(self.gitlab, self.configuration, self.strict)
|
|
121
|
+
self.project_processors = ProjectProcessors(self.gitlab, self.configuration, self.strict, self.log_level)
|
|
112
122
|
self.groups_provider = GroupsProvider(
|
|
113
123
|
self.gitlab,
|
|
114
124
|
self.configuration,
|
|
@@ -323,27 +333,24 @@ class GitLabForm:
|
|
|
323
333
|
args.recurse_subsgroups,
|
|
324
334
|
)
|
|
325
335
|
|
|
326
|
-
def
|
|
336
|
+
def _configure_logging(self) -> None:
|
|
327
337
|
"""
|
|
328
338
|
Configures the application output using logging, based on debug and verbose flags:
|
|
329
339
|
|
|
330
340
|
* normal mode - logging only WARNING logs
|
|
331
341
|
* verbose mode - logging INFO level and above
|
|
332
342
|
* debug / tests mode - logging DEBUG level and above, along with rich exception tracebacks (may expose secrets)
|
|
333
|
-
|
|
334
|
-
:param tests: True if we are running in tests mode
|
|
335
343
|
"""
|
|
336
344
|
rich_tracebacks = False
|
|
337
|
-
|
|
338
|
-
|
|
345
|
+
|
|
346
|
+
if self.log_level == logging.DEBUG:
|
|
339
347
|
rich_tracebacks = True
|
|
340
|
-
elif self.verbose:
|
|
341
|
-
level = logging.INFO
|
|
342
|
-
else:
|
|
343
|
-
level = logging.WARNING
|
|
344
348
|
|
|
345
349
|
logging.basicConfig(
|
|
346
|
-
level=
|
|
350
|
+
level=self.log_level,
|
|
351
|
+
format="%(message)s",
|
|
352
|
+
datefmt="[%X]",
|
|
353
|
+
handlers=[RichHandler(rich_tracebacks=rich_tracebacks)],
|
|
347
354
|
)
|
|
348
355
|
|
|
349
356
|
def _initialize_configuration_and_gitlab(self) -> Tuple[GitLab, Configuration]:
|
|
@@ -362,7 +369,7 @@ class GitLabForm:
|
|
|
362
369
|
gitlab = GitLab(config_path=self.config)
|
|
363
370
|
configuration = gitlab.get_configuration()
|
|
364
371
|
|
|
365
|
-
configuration_transformers = ConfigurationTransformers(gitlab)
|
|
372
|
+
configuration_transformers = ConfigurationTransformers(gitlab, self.log_level)
|
|
366
373
|
configuration_transformers.transform(configuration)
|
|
367
374
|
|
|
368
375
|
except ConfigFileNotFoundException as e:
|
|
@@ -93,10 +93,6 @@ class ConfigurationCore(ABC):
|
|
|
93
93
|
|
|
94
94
|
yaml = Parsers.get_yaml_editor()
|
|
95
95
|
|
|
96
|
-
# for better backward compatibility with PyYAML (that supports only YAML 1.1) used in the previous
|
|
97
|
-
# GitLabForm versions, let's force ruamel.yaml to use YAML version 1.1 by default too
|
|
98
|
-
yaml.version = (1, 1)
|
|
99
|
-
|
|
100
96
|
if config_string:
|
|
101
97
|
config = textwrap.dedent(source)
|
|
102
98
|
info("Reading config from the provided string.")
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
from logging import debug, info, critical
|
|
2
|
+
from logging import debug, info, critical, DEBUG
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
-
from ez_yaml import ez_yaml
|
|
5
|
-
from ruamel.yaml import YAML
|
|
6
4
|
from types import SimpleNamespace
|
|
7
|
-
|
|
8
5
|
from ruamel.yaml.comments import CommentedMap
|
|
9
6
|
from yamlpath import Processor
|
|
10
7
|
from yamlpath.exceptions import YAMLPathException
|
|
11
8
|
from yamlpath.wrappers import ConsolePrinter
|
|
12
9
|
|
|
10
|
+
from gitlabform import util
|
|
13
11
|
from gitlabform.constants import EXIT_INVALID_INPUT, APPROVAL_RULE_NAME
|
|
14
12
|
from gitlabform.configuration import Configuration
|
|
15
13
|
from gitlabform.gitlab import AccessLevel
|
|
@@ -24,23 +22,26 @@ from gitlabform.gitlab import GitLab
|
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
class ConfigurationTransformers:
|
|
27
|
-
def __init__(self, gitlab: GitLab):
|
|
25
|
+
def __init__(self, gitlab: GitLab, log_level: int):
|
|
28
26
|
self.user_transformer = UserTransformer(gitlab)
|
|
29
27
|
self.group_transformer = GroupTransformer(gitlab)
|
|
30
28
|
self.implicit_name_transformer = ImplicitNameTransformer(gitlab)
|
|
31
29
|
self.access_level_transformer = AccessLevelsTransformer(gitlab)
|
|
30
|
+
self.log_level = log_level
|
|
32
31
|
|
|
33
32
|
def transform(self, configuration: Configuration) -> None:
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if self.log_level == DEBUG:
|
|
34
|
+
config_before = util.yaml_config_to_string(configuration.config)
|
|
35
|
+
debug(f"Config BEFORE transformations:\n{config_before}")
|
|
36
36
|
|
|
37
37
|
self.user_transformer.transform(configuration)
|
|
38
38
|
self.group_transformer.transform(configuration)
|
|
39
39
|
self.implicit_name_transformer.transform(configuration)
|
|
40
40
|
self.access_level_transformer.transform(configuration, last=True)
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
if self.log_level == DEBUG:
|
|
43
|
+
config_after = util.yaml_config_to_string(configuration.config)
|
|
44
|
+
debug(f"Config AFTER transformations:\n{config_after}")
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
class ConfigurationTransformer(ABC):
|
|
@@ -58,9 +59,9 @@ class ConfigurationTransformer(ABC):
|
|
|
58
59
|
# we needed complex ruamel.yaml's types like ordereddict and CommentedSeq
|
|
59
60
|
# for transformations, but at the end convert them to simple dict and lists
|
|
60
61
|
# for easier to understand debug output and tests
|
|
62
|
+
config_yaml_string = util.yaml_config_to_string(configuration.config)
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
simple_yaml_loader = YAML(typ="safe", pure=True)
|
|
64
|
+
simple_yaml_loader = util.configure_ruamel_yaml_loader(typ="safe", pure=True)
|
|
64
65
|
configuration.config = simple_yaml_loader.load(config_yaml_string)
|
|
65
66
|
|
|
66
67
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from logging import debug, critical, info
|
|
3
3
|
|
|
4
|
-
import
|
|
5
|
-
|
|
4
|
+
from gitlabform import util
|
|
6
5
|
from gitlabform.constants import EXIT_INVALID_INPUT, EXIT_PROCESSING_ERROR
|
|
7
6
|
|
|
8
7
|
|
|
@@ -38,7 +37,7 @@ class EffectiveConfigurationFile:
|
|
|
38
37
|
def write_to_file(self):
|
|
39
38
|
if self.output_file:
|
|
40
39
|
try:
|
|
41
|
-
yaml_configuration =
|
|
40
|
+
yaml_configuration = util.yaml_config_to_string(self.config)
|
|
42
41
|
self.output_file.write(yaml_configuration)
|
|
43
42
|
self.output_file.close()
|
|
44
43
|
except Exception as e:
|
|
@@ -47,7 +47,7 @@ from gitlabform.processors.project.remote_mirrors_processor import RemoteMirrors
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
class ProjectProcessors(AbstractProcessors):
|
|
50
|
-
def __init__(self, gitlab: GitLab, config: Configuration, strict: bool):
|
|
50
|
+
def __init__(self, gitlab: GitLab, config: Configuration, strict: bool, log_level: int):
|
|
51
51
|
super().__init__(gitlab, config, strict)
|
|
52
52
|
self.processors: List[AbstractProcessor] = [
|
|
53
53
|
# Order of processors matter. GitLabForm will process config sections
|
|
@@ -64,7 +64,7 @@ class ProjectProcessors(AbstractProcessors):
|
|
|
64
64
|
ProjectLabelsProcessor(gitlab),
|
|
65
65
|
JobTokenScopeProcessor(gitlab),
|
|
66
66
|
DeployKeysProcessor(gitlab),
|
|
67
|
-
ProjectVariablesProcessor(gitlab),
|
|
67
|
+
ProjectVariablesProcessor(gitlab, log_level),
|
|
68
68
|
BranchesProcessor(gitlab, strict),
|
|
69
69
|
TagsProcessor(gitlab, strict),
|
|
70
70
|
IntegrationsProcessor(gitlab),
|
{gitlabform-5.5.6 → gitlabform-6.0.0}/gitlabform/processors/project/project_variables_processor.py
RENAMED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
from typing import Dict, Any, List, cast
|
|
2
|
-
from logging import warning, info
|
|
2
|
+
from logging import warning, info, INFO
|
|
3
3
|
|
|
4
4
|
import copy
|
|
5
5
|
import textwrap
|
|
6
|
-
import ez_yaml
|
|
7
6
|
|
|
8
7
|
from gitlab.exceptions import GitlabGetError
|
|
9
8
|
from gitlab.v4.objects import Project, ProjectVariable
|
|
9
|
+
|
|
10
|
+
from gitlabform import util
|
|
10
11
|
from gitlabform.gitlab import GitLab
|
|
11
12
|
from gitlabform.processors.util.difference_logger import hide
|
|
12
13
|
from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
@@ -14,8 +15,9 @@ from gitlabform.processors.util.variables_processor import VariablesProcessor
|
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class ProjectVariablesProcessor(AbstractProcessor):
|
|
17
|
-
def __init__(self, gitlab: GitLab):
|
|
18
|
+
def __init__(self, gitlab: GitLab, log_level: int):
|
|
18
19
|
super().__init__("variables", gitlab)
|
|
20
|
+
self.log_level = log_level
|
|
19
21
|
self._variables_processor = VariablesProcessor(self._needs_update)
|
|
20
22
|
|
|
21
23
|
def _process_configuration(self, project_and_group: str, configuration: Dict[str, Any]) -> None:
|
|
@@ -65,12 +67,14 @@ class ProjectVariablesProcessor(AbstractProcessor):
|
|
|
65
67
|
variables_list.append(var_dict)
|
|
66
68
|
|
|
67
69
|
info(f"Variables for {project_and_group} in GitLab:")
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
if self.log_level == INFO:
|
|
71
|
+
yaml = util.yaml_config_to_string(variables_list)
|
|
72
|
+
info(
|
|
73
|
+
textwrap.indent(
|
|
74
|
+
yaml,
|
|
75
|
+
" ",
|
|
76
|
+
)
|
|
72
77
|
)
|
|
73
|
-
)
|
|
74
78
|
except GitlabGetError:
|
|
75
79
|
info(f"Variables for {project_and_group} in GitLab cannot be checked.")
|
|
76
80
|
|
|
@@ -86,9 +90,11 @@ class ProjectVariablesProcessor(AbstractProcessor):
|
|
|
86
90
|
for key in configured_variables.keys():
|
|
87
91
|
configured_variables[key]["value"] = hide(configured_variables[key]["value"])
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
if self.log_level == INFO:
|
|
94
|
+
yaml = util.yaml_config_to_string(configured_variables)
|
|
95
|
+
info(
|
|
96
|
+
textwrap.indent(
|
|
97
|
+
"",
|
|
98
|
+
" ",
|
|
99
|
+
)
|
|
93
100
|
)
|
|
94
|
-
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from io import StringIO
|
|
3
|
+
|
|
4
|
+
from ruamel.yaml import YAML
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def to_str(a_dict: dict) -> str:
|
|
8
|
+
# arguably the most readable form of a dict in a single line
|
|
9
|
+
# is JSON with sorted keys
|
|
10
|
+
return json.dumps(a_dict, sort_keys=True, default=str)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def yaml_config_to_string(yaml) -> str:
|
|
14
|
+
"""
|
|
15
|
+
Provides a convenience wrapper around ruamel.yaml to output to a string
|
|
16
|
+
ez_yaml used to perform this task but in v2.2 they seem to have over complicated the implementation and it is
|
|
17
|
+
breaking in ruamel.yaml when parsing the yaml, with no way for us to configure it.
|
|
18
|
+
We can provide a simple native implementation around ruamel.yaml to configure it consistently.
|
|
19
|
+
:param yaml:
|
|
20
|
+
:return:
|
|
21
|
+
"""
|
|
22
|
+
yaml_loader = configure_ruamel_yaml_loader()
|
|
23
|
+
|
|
24
|
+
# dump to StringIO
|
|
25
|
+
string_stream = StringIO()
|
|
26
|
+
yaml_loader.dump(yaml, string_stream)
|
|
27
|
+
config_yaml_string = string_stream.getvalue()
|
|
28
|
+
string_stream.close()
|
|
29
|
+
|
|
30
|
+
return config_yaml_string
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def configure_ruamel_yaml_loader(typ=None, pure=False, output=None, plug_ins=None) -> YAML:
|
|
34
|
+
"""
|
|
35
|
+
Takes inputs matching ruamel.yaml __init__ and configures with indentation, duplicate key allowance and null representor
|
|
36
|
+
:return: instance of ruamel.yaml
|
|
37
|
+
"""
|
|
38
|
+
yaml_loader = YAML(typ=typ, pure=pure, output=output, plug_ins=plug_ins)
|
|
39
|
+
yaml_loader.indent(mapping=3, sequence=2, offset=0)
|
|
40
|
+
yaml_loader.allow_duplicate_keys = True
|
|
41
|
+
yaml_loader.explicit_start = False
|
|
42
|
+
# show null
|
|
43
|
+
yaml_loader.representer.add_representer(
|
|
44
|
+
type(None),
|
|
45
|
+
lambda self, data: self.represent_scalar("tag:yaml.org,2002:null", "null"),
|
|
46
|
+
)
|
|
47
|
+
return yaml_loader
|
|
@@ -10,7 +10,7 @@ packages = ["gitlabform"]
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "gitlabform"
|
|
13
|
-
version = "
|
|
13
|
+
version = "6.0.0"
|
|
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"
|
|
@@ -33,8 +33,6 @@ classifiers = [
|
|
|
33
33
|
dependencies = [
|
|
34
34
|
"certifi==2026.5.20",
|
|
35
35
|
"cli-ui==0.19.0",
|
|
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
|
-
"ez-yaml==1.2.0",
|
|
38
36
|
"jinja2==3.1.6",
|
|
39
37
|
"luddite==1.0.4",
|
|
40
38
|
"markupsafe==3.0.3",
|
|
@@ -43,11 +41,8 @@ dependencies = [
|
|
|
43
41
|
"python-gitlab[graphql]==8.4.0",
|
|
44
42
|
"requests==2.34.2",
|
|
45
43
|
"rich==15.0.0",
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# unannotated yaml 1.1
|
|
49
|
-
"ruamel.yaml==0.17.21",
|
|
50
|
-
"yamlpath==3.8.2",
|
|
44
|
+
"ruamel.yaml==0.19.1",
|
|
45
|
+
"yamlpath==3.9.1",
|
|
51
46
|
]
|
|
52
47
|
|
|
53
48
|
# PEP 735 Dependency Groups.
|
|
@@ -65,7 +60,6 @@ dev = [
|
|
|
65
60
|
test = [
|
|
66
61
|
"coverage==7.14.1",
|
|
67
62
|
"cryptography==49.0.0",
|
|
68
|
-
"deepdiff==9.1.0",
|
|
69
63
|
"pytest==9.1.0",
|
|
70
64
|
"pytest-cov==7.1.0",
|
|
71
65
|
"pytest-rerunfailures==16.3",
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from gitlabform.configuration import Configuration
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.fixture
|
|
7
|
+
def yaml11_configuration_with_yes():
|
|
8
|
+
config_yaml = """
|
|
9
|
+
---
|
|
10
|
+
projects_and_groups:
|
|
11
|
+
some_group/*:
|
|
12
|
+
project_settings:
|
|
13
|
+
foo: yes # in YAML 1.1 this should be interpreted as boolean true
|
|
14
|
+
"""
|
|
15
|
+
return Configuration(config_string=config_yaml)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def yaml12_configuration():
|
|
20
|
+
config_yaml = """
|
|
21
|
+
%YAML 1.2
|
|
22
|
+
---
|
|
23
|
+
projects_and_groups:
|
|
24
|
+
some_group/*:
|
|
25
|
+
project_settings:
|
|
26
|
+
foo: true
|
|
27
|
+
"""
|
|
28
|
+
return Configuration(config_string=config_yaml)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture
|
|
32
|
+
def yaml11_annotated_configuration_with_yes():
|
|
33
|
+
config_yaml = """
|
|
34
|
+
%YAML 1.1
|
|
35
|
+
---
|
|
36
|
+
projects_and_groups:
|
|
37
|
+
some_group/*:
|
|
38
|
+
project_settings:
|
|
39
|
+
foo: yes # in YAML 1.1 this should be interpreted as boolean true
|
|
40
|
+
"""
|
|
41
|
+
return Configuration(config_string=config_yaml)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test__unannotated_yaml_11(yaml11_configuration_with_yes):
|
|
45
|
+
"""
|
|
46
|
+
By default, in v6.+ we use YAML 1.2, so the "yes" value is not interpreted as a boolean.
|
|
47
|
+
This test validates that without annotation, the YAML file is treated as v1.2, and "yes" is just a string, not a boolean.
|
|
48
|
+
"""
|
|
49
|
+
assert yaml11_configuration_with_yes.get("projects_and_groups|some_group/*|project_settings") == {"foo": "yes"}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test__annotated_yaml_11(yaml11_annotated_configuration_with_yes):
|
|
53
|
+
"""
|
|
54
|
+
By default, in v6.+ we use YAML 1.2, so the "yes" value is not interpreted as a boolean, unless annotated as such.
|
|
55
|
+
This test validates the annotation can correctly set a YAML file to v1.1
|
|
56
|
+
"""
|
|
57
|
+
assert yaml11_annotated_configuration_with_yes.get("projects_and_groups|some_group/*|project_settings") == {
|
|
58
|
+
"foo": True
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test__yaml_12(yaml12_configuration):
|
|
63
|
+
assert yaml12_configuration.get("projects_and_groups|some_group/*|project_settings") == {"foo": True}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
from unittest import TestCase
|
|
2
|
-
|
|
3
|
-
import ez_yaml
|
|
4
1
|
import pytest
|
|
5
|
-
from deepdiff import DeepDiff
|
|
6
2
|
from unittest.mock import MagicMock
|
|
7
3
|
|
|
8
|
-
from gitlabform.constants import APPROVAL_RULE_NAME
|
|
9
4
|
from gitlabform import EXIT_INVALID_INPUT
|
|
10
5
|
from gitlabform.configuration import Configuration
|
|
11
6
|
from gitlabform.configuration.transform import (
|
|
@@ -86,8 +81,7 @@ def test__config__with_access_level_names__branches():
|
|
|
86
81
|
"""
|
|
87
82
|
configuration_with_numbers = Configuration(config_string=config_with_numbers)
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
assert not ddiff
|
|
84
|
+
assert configuration.config == configuration_with_numbers.config
|
|
91
85
|
|
|
92
86
|
|
|
93
87
|
def test__config__with_access_level_names__group_ldap_links():
|
|
@@ -128,8 +122,7 @@ def test__config__with_access_level_names__group_ldap_links():
|
|
|
128
122
|
"""
|
|
129
123
|
configuration_with_numbers = Configuration(config_string=config_with_numbers)
|
|
130
124
|
|
|
131
|
-
|
|
132
|
-
assert not ddiff
|
|
125
|
+
assert configuration_with_numbers.config == configuration_with_numbers.config
|
|
133
126
|
|
|
134
127
|
|
|
135
128
|
def test__config__with_access_level_names__branches_premium_syntax():
|
|
@@ -174,8 +167,7 @@ def test__config__with_access_level_names__branches_premium_syntax():
|
|
|
174
167
|
"""
|
|
175
168
|
configuration_with_numbers = Configuration(config_string=config_with_numbers)
|
|
176
169
|
|
|
177
|
-
|
|
178
|
-
assert not ddiff
|
|
170
|
+
assert configuration.config == configuration_with_numbers.config
|
|
179
171
|
|
|
180
172
|
|
|
181
173
|
def test__config__with_access_level_names__invalid_name():
|
{gitlabform-5.5.6 → gitlabform-6.0.0}/tests/unit/configuration/transform/test_group_transformer.py
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from deepdiff import DeepDiff
|
|
2
1
|
from unittest.mock import MagicMock
|
|
3
2
|
|
|
4
3
|
from gitlabform.configuration import Configuration
|
|
@@ -29,10 +28,6 @@ def test__transform_for_merge_request_approvals() -> None:
|
|
|
29
28
|
|
|
30
29
|
assert gitlab_mock._get_group_id.call_count == 1
|
|
31
30
|
|
|
32
|
-
# effective_config_yaml_str = ez_yaml.to_string(obj=configuration.config, options={})
|
|
33
|
-
# print("!!!")
|
|
34
|
-
# print(effective_config_yaml_str)
|
|
35
|
-
|
|
36
31
|
expected_transformed_config_yaml = f"""
|
|
37
32
|
projects_and_groups:
|
|
38
33
|
"foo/bar":
|
|
@@ -45,6 +40,5 @@ def test__transform_for_merge_request_approvals() -> None:
|
|
|
45
40
|
"""
|
|
46
41
|
|
|
47
42
|
expected_transformed_config = Configuration(config_string=expected_transformed_config_yaml)
|
|
48
|
-
transformer.convert_to_simple_types(expected_transformed_config)
|
|
49
43
|
|
|
50
|
-
assert
|
|
44
|
+
assert configuration.config == expected_transformed_config.config
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from deepdiff import DeepDiff
|
|
2
1
|
from unittest.mock import MagicMock
|
|
3
2
|
|
|
4
3
|
from gitlabform.configuration import Configuration
|
|
@@ -31,7 +30,7 @@ def test__transform_for_protected_environments():
|
|
|
31
30
|
|
|
32
31
|
expected_transformed_config = Configuration(config_string=expected_transformed_config_yaml)
|
|
33
32
|
|
|
34
|
-
assert
|
|
33
|
+
assert configuration.config == expected_transformed_config.config
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
def test__transform_for_protected_environments_sanity_check():
|
|
@@ -47,4 +46,4 @@ def test__transform_for_protected_environments_sanity_check():
|
|
|
47
46
|
|
|
48
47
|
expected_transformed_config = Configuration(config_string=expected_transformed_config_yaml)
|
|
49
48
|
|
|
50
|
-
assert
|
|
49
|
+
assert configuration.config != expected_transformed_config.config
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import ez_yaml
|
|
2
|
-
from deepdiff import DeepDiff
|
|
3
|
-
from pprint import pprint
|
|
4
1
|
from unittest.mock import MagicMock
|
|
5
2
|
|
|
6
3
|
from gitlabform.configuration import Configuration
|
|
@@ -35,7 +32,6 @@ def test__transform_for_merge_request_approvals() -> None:
|
|
|
35
32
|
gitlab_mock = MagicMock(GitLab)
|
|
36
33
|
gitlab_mock._get_group_id = MagicMock(side_effect=[1])
|
|
37
34
|
gitlab_mock._get_user_id = MagicMock(side_effect=[2])
|
|
38
|
-
# gitlab_mock._get_branch_id = MagicMock(side_effect=[3])
|
|
39
35
|
|
|
40
36
|
ut = UserTransformer(gitlab_mock)
|
|
41
37
|
ut.transform(configuration)
|
|
@@ -43,13 +39,6 @@ def test__transform_for_merge_request_approvals() -> None:
|
|
|
43
39
|
gt = GroupTransformer(gitlab_mock)
|
|
44
40
|
gt.transform(configuration, last=True)
|
|
45
41
|
|
|
46
|
-
# ut = UserTransformer(gitlab_mock)
|
|
47
|
-
# ut.transform(configuration)
|
|
48
|
-
|
|
49
|
-
effective_config_yaml_str = ez_yaml.to_string(obj=configuration.config, options={})
|
|
50
|
-
print("!!!BEFORE:")
|
|
51
|
-
print(effective_config_yaml_str)
|
|
52
|
-
|
|
53
42
|
expected_transformed_config_yaml = f"""
|
|
54
43
|
projects_and_groups:
|
|
55
44
|
|
|
@@ -70,11 +59,4 @@ def test__transform_for_merge_request_approvals() -> None:
|
|
|
70
59
|
|
|
71
60
|
expected_transformed_config = Configuration(config_string=expected_transformed_config_yaml)
|
|
72
61
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
effective_config_yaml_str = ez_yaml.to_string(obj=expected_transformed_config.config, options={})
|
|
76
|
-
print("!!!After:")
|
|
77
|
-
print(effective_config_yaml_str)
|
|
78
|
-
|
|
79
|
-
difference = DeepDiff(configuration.config, expected_transformed_config.config)
|
|
80
|
-
assert not difference
|
|
62
|
+
assert configuration.config == expected_transformed_config.config
|