Coverage for src/gitlabracadabra/mixins/milestones.py: 72%
50 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-14 23:10 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-14 23:10 +0200
1#
2# Copyright (C) 2019-2025 Mathieu Parent <math.parent@gmail.com>
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Lesser General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
17import logging
18from copy import deepcopy
20from gitlabracadabra.objects.object import GitLabracadabraObject
22logger = logging.getLogger(__name__)
25class MilestonesMixin(GitLabracadabraObject):
26 """Object with milestones."""
28 """_process_milestones()
30 Process the milestones param.
31 """
33 def _process_milestones(self, param_name, param_value, *, dry_run=False, skip_save=False):
34 assert param_name == "milestones" # noqa: S101
35 assert not skip_save # noqa: S101
36 unknown_milestones = self._content.get("unknown_milestones", "warn")
37 try:
38 current_milestones = dict(
39 [
40 [current_milestone.title, current_milestone]
41 for current_milestone in self._obj.milestones.list(all=True)
42 ]
43 )
44 except AttributeError:
45 # https://github.com/python-gitlab/python-gitlab/pull/847
46 logger.error(
47 "[%s] Unable to manage milestones: %s", self._name, "group milestones requires python-gitlab >= 1.1.0"
48 )
49 return
50 target_milestones = dict(
51 [[target_milestone["title"], deepcopy(target_milestone)] for target_milestone in param_value]
52 )
53 # We first check for already existing milestones
54 for current_milestone_title, current_milestone in sorted(current_milestones.items()):
55 if current_milestone_title in target_milestones:
56 for target_milestone_param_name, target_milestone_param_value in sorted(
57 target_milestones[current_milestone_title].items()
58 ):
59 try:
60 current_milestone_param_value = getattr(current_milestone, target_milestone_param_name)
61 except AttributeError:
62 logger.info(
63 "[%s] NOT Changing milestone %s %s: %s -> %s (current value is not available)",
64 self._name,
65 current_milestone_title,
66 target_milestone_param_name,
67 None,
68 target_milestone_param_value,
69 )
70 continue
71 if current_milestone_param_value is None: 71 ↛ 72line 71 didn't jump to line 72 because the condition on line 71 was never true
72 current_milestone_param_value = ""
73 if current_milestone_param_value != target_milestone_param_value:
74 if target_milestone_param_name == "state":
75 target_milestone_param_name = "state_event"
76 if target_milestone_param_value == "closed": 76 ↛ 79line 76 didn't jump to line 79 because the condition on line 76 was always true
77 target_milestone_param_value = "close"
78 else:
79 target_milestone_param_value = "activate"
80 if dry_run: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true
81 logger.info(
82 "[%s] NOT Changing milestone %s %s: %s -> %s (dry-run)",
83 self._name,
84 current_milestone_title,
85 target_milestone_param_name,
86 current_milestone_param_value,
87 target_milestone_param_value,
88 )
89 else:
90 logger.info(
91 "[%s] Changing milestone %s %s: %s -> %s",
92 self._name,
93 current_milestone_title,
94 target_milestone_param_name,
95 current_milestone_param_value,
96 target_milestone_param_value,
97 )
98 setattr(current_milestone, target_milestone_param_name, target_milestone_param_value)
99 current_milestone.save()
100 target_milestones.pop(current_milestone_title)
101 elif unknown_milestones in ["delete", "remove"]: 101 ↛ 107line 101 didn't jump to line 107 because the condition on line 101 was always true
102 if dry_run: 102 ↛ 103line 102 didn't jump to line 103 because the condition on line 102 was never true
103 logger.info("[%s] NOT Removing milestone %s (dry-run)", self._name, current_milestone_title)
104 else:
105 logger.info("[%s] Removing milestone %s", self._name, current_milestone_title)
106 current_milestone.delete()
107 elif unknown_milestones not in ["ignore", "skip"]:
108 logger.warning("[%s] NOT Removing milestone: %s", self._name, current_milestone_title)
109 # Remaining milestones
110 for target_milestone_title, target_milestone in sorted(target_milestones.items()):
111 if dry_run: 111 ↛ 112line 111 didn't jump to line 112 because the condition on line 111 was never true
112 logger.info(
113 "[%s] NOT Adding milestone %s: %s -> %s (dry-run)",
114 self._name,
115 target_milestone_title,
116 None,
117 target_milestone,
118 )
119 else:
120 logger.info(
121 "[%s] Adding milestone %s: %s -> %s", self._name, target_milestone_title, None, target_milestone
122 )
123 self._obj.milestones.create(target_milestone)