Loading gitlab_butler/butler.py +13 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,7 @@ class Butler: def cleaning_enabled_project(self, project: Project) -> bool: """ Check if project should be cleaned. Projects can be excluded or be in read-only mode. Check if project should be cleaned. Projects can be excluded or be in read-only mode. Also check if our access level is high enough. :param project: :return: True if project should be cleaned, False otherwise """ Loading @@ -226,6 +226,18 @@ class Butler: ) return False # check if access level is high enough to process project (*_access can be missing or explicitly set to None) access_level = max( (project.permissions.get('project_access') or {}).get('access_level', 0), (project.permissions.get('group_access') or {}).get('access_level', 0) ) if access_level < 30: print( f" - 🏠 Project {AnsiColors.BLUE}{project.path_with_namespace}{AnsiColors.RESET} access right is too low, check token: {AnsiColors.HGRAY}skip{AnsiColors.RESET}" ) return False return True def find_pipeline_source_status(self, project: Project, pipeline: ProjectPipeline, caches: dict) -> PipelineSource | None: Loading poetry.lock +170 −165 File changed.Preview size limit exceeded, changes collapsed. Show changes tests/test_groups.py +44 −3 Original line number Diff line number Diff line Loading @@ -7,9 +7,14 @@ from gitlab_butler.main import to_url # project details : https://docs.gitlab.com/ee/api/projects.html#get-single-project def mock_empty_project(project_id, archived: bool = False): def mock_empty_project(project_id, archived: bool = False, project_access: int = 30, group_access: int = 30): permission = dict() permission['project_access'] = { 'access_level': project_access } if project_access is not None else None permission['group_access'] = { 'access_level': group_access } if group_access is not None else None responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}', status=200, json= {'id': project_id, 'path': f'project_{project_id}', 'path_with_namespace': f'path/to/group/project_{project_id}', 'default_branch': 'main', 'archived': archived} {'id': project_id, 'path': f'project_{project_id}', 'path_with_namespace': f'path/to/group/project_{project_id}', 'default_branch': 'main', 'archived': archived, 'permissions': permission } ) responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/repository/files/.butlercfg.yaml?ref=main', status=404) responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/repository/files/.butlercfg.yml?ref=main', status=404) Loading @@ -17,7 +22,6 @@ def mock_empty_project(project_id, archived: bool = False): responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/repository/tags?per_page=100', status=200, json=[]) responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/pipelines?sort=asc&order_by=updated_at&per_page=100', status=200, json=[]) class TestGroups: @staticmethod def create_butler() -> Butler: Loading Loading @@ -230,5 +234,42 @@ class TestGroups: assert butler.groups_count == 1 assert butler.projects_count == 2 @responses.activate def test_process_group_access_levels(self): butler = self.create_butler() # setup mock responses responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/path%2Fto%2Fgroup', status=200, json={'id': 42, 'name': 'Test Group', 'full_path': 'path/to/group'}) responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/43', status=200, json={'id': 43, 'name': 'Sub Group 1', 'full_path': 'path/to/group/sub1'}) responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/42/projects?per_page=100', status=200, json=[ {'id': 1000, 'path': 'path/to/group/project0'}, {'id': 1001, 'path': 'path/to/group/project1'}, {'id': 1002, 'path': 'path/to/group/project2'}, {'id': 1003, 'path': 'path/to/group/project3'}, {'id': 1004, 'path': 'path/to/group/project4'}, {'id': 1005, 'path': 'path/to/group/project5'}, ]) responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/42/descendant_groups?per_page=100', status=200, json=[]) # Setup empty project mock_empty_project('1000', project_access=None, group_access=None) # no access mock_empty_project('1001', project_access=10, group_access=None) # project access too low mock_empty_project('1002', project_access=30, group_access=None) # project access ok mock_empty_project('1003', project_access=None, group_access=10) # group access too low mock_empty_project('1004', project_access=None, group_access=30) # group access ok mock_empty_project('1005', project_access=10, group_access=30) # project access too low but group access ok # get initial group group = butler.client.groups.get(butler.group_path) assert group.id == 42 and group.name == 'Test Group' # clean initial group butler.clean_group(group) assert butler.groups_count == 1 assert butler.projects_count == 3 Loading
gitlab_butler/butler.py +13 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,7 @@ class Butler: def cleaning_enabled_project(self, project: Project) -> bool: """ Check if project should be cleaned. Projects can be excluded or be in read-only mode. Check if project should be cleaned. Projects can be excluded or be in read-only mode. Also check if our access level is high enough. :param project: :return: True if project should be cleaned, False otherwise """ Loading @@ -226,6 +226,18 @@ class Butler: ) return False # check if access level is high enough to process project (*_access can be missing or explicitly set to None) access_level = max( (project.permissions.get('project_access') or {}).get('access_level', 0), (project.permissions.get('group_access') or {}).get('access_level', 0) ) if access_level < 30: print( f" - 🏠 Project {AnsiColors.BLUE}{project.path_with_namespace}{AnsiColors.RESET} access right is too low, check token: {AnsiColors.HGRAY}skip{AnsiColors.RESET}" ) return False return True def find_pipeline_source_status(self, project: Project, pipeline: ProjectPipeline, caches: dict) -> PipelineSource | None: Loading
tests/test_groups.py +44 −3 Original line number Diff line number Diff line Loading @@ -7,9 +7,14 @@ from gitlab_butler.main import to_url # project details : https://docs.gitlab.com/ee/api/projects.html#get-single-project def mock_empty_project(project_id, archived: bool = False): def mock_empty_project(project_id, archived: bool = False, project_access: int = 30, group_access: int = 30): permission = dict() permission['project_access'] = { 'access_level': project_access } if project_access is not None else None permission['group_access'] = { 'access_level': group_access } if group_access is not None else None responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}', status=200, json= {'id': project_id, 'path': f'project_{project_id}', 'path_with_namespace': f'path/to/group/project_{project_id}', 'default_branch': 'main', 'archived': archived} {'id': project_id, 'path': f'project_{project_id}', 'path_with_namespace': f'path/to/group/project_{project_id}', 'default_branch': 'main', 'archived': archived, 'permissions': permission } ) responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/repository/files/.butlercfg.yaml?ref=main', status=404) responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/repository/files/.butlercfg.yml?ref=main', status=404) Loading @@ -17,7 +22,6 @@ def mock_empty_project(project_id, archived: bool = False): responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/repository/tags?per_page=100', status=200, json=[]) responses.add(responses.GET, f'http://gitlab.test/api/v4/projects/{project_id}/pipelines?sort=asc&order_by=updated_at&per_page=100', status=200, json=[]) class TestGroups: @staticmethod def create_butler() -> Butler: Loading Loading @@ -230,5 +234,42 @@ class TestGroups: assert butler.groups_count == 1 assert butler.projects_count == 2 @responses.activate def test_process_group_access_levels(self): butler = self.create_butler() # setup mock responses responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/path%2Fto%2Fgroup', status=200, json={'id': 42, 'name': 'Test Group', 'full_path': 'path/to/group'}) responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/43', status=200, json={'id': 43, 'name': 'Sub Group 1', 'full_path': 'path/to/group/sub1'}) responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/42/projects?per_page=100', status=200, json=[ {'id': 1000, 'path': 'path/to/group/project0'}, {'id': 1001, 'path': 'path/to/group/project1'}, {'id': 1002, 'path': 'path/to/group/project2'}, {'id': 1003, 'path': 'path/to/group/project3'}, {'id': 1004, 'path': 'path/to/group/project4'}, {'id': 1005, 'path': 'path/to/group/project5'}, ]) responses.add(responses.GET, 'http://gitlab.test/api/v4/groups/42/descendant_groups?per_page=100', status=200, json=[]) # Setup empty project mock_empty_project('1000', project_access=None, group_access=None) # no access mock_empty_project('1001', project_access=10, group_access=None) # project access too low mock_empty_project('1002', project_access=30, group_access=None) # project access ok mock_empty_project('1003', project_access=None, group_access=10) # group access too low mock_empty_project('1004', project_access=None, group_access=30) # group access ok mock_empty_project('1005', project_access=10, group_access=30) # project access too low but group access ok # get initial group group = butler.client.groups.get(butler.group_path) assert group.id == 42 and group.name == 'Test Group' # clean initial group butler.clean_group(group) assert butler.groups_count == 1 assert butler.projects_count == 3