Skip to content

Commit 59738a1

Browse files
authored
Merge pull request #5995 from stsewd/update-automation-rules-model
Add manager and description field to AutomationRule model
2 parents 0f80a2e + aadef61 commit 59738a1

File tree

4 files changed

+168
-33
lines changed

4 files changed

+168
-33
lines changed

readthedocs/builds/managers.py

+50-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
# -*- coding: utf-8 -*-
2-
31
"""Build and Version class model Managers."""
42

53
import logging
64

7-
from django.db import models
85
from django.core.exceptions import ObjectDoesNotExist
6+
from django.db import models
7+
from polymorphic.managers import PolymorphicManager
98

109
from readthedocs.core.utils.extend import (
1110
SettingsOverrideObject,
@@ -14,14 +13,15 @@
1413

1514
from .constants import (
1615
BRANCH,
16+
EXTERNAL,
1717
LATEST,
1818
LATEST_VERBOSE_NAME,
1919
STABLE,
2020
STABLE_VERBOSE_NAME,
2121
TAG,
22-
EXTERNAL,
2322
)
24-
from .querysets import VersionQuerySet, BuildQuerySet
23+
from .querysets import BuildQuerySet, VersionQuerySet
24+
2525

2626
log = logging.getLogger(__name__)
2727

@@ -179,3 +179,48 @@ class InternalBuildManager(SettingsOverrideObject):
179179

180180
class ExternalBuildManager(SettingsOverrideObject):
181181
_default_class = ExternalBuildManagerBase
182+
183+
184+
class VersionAutomationRuleManager(PolymorphicManager):
185+
186+
"""
187+
Mananger for VersionAutomationRule.
188+
189+
.. note::
190+
191+
This manager needs to inherit from PolymorphicManager,
192+
since the model is a PolymorphicModel.
193+
See https://django-polymorphic.readthedocs.io/page/managers.html
194+
"""
195+
196+
def add_rule(
197+
self, *, project, description, match_arg, version_type,
198+
action, action_arg=None,
199+
):
200+
"""
201+
Append an automation rule to `project`.
202+
203+
The rule is created with a priority lower than the last rule
204+
in `project`.
205+
"""
206+
last_priority = (
207+
project.automation_rules
208+
.values_list('priority', flat=True)
209+
.order_by('priority')
210+
.last()
211+
)
212+
if last_priority is None:
213+
priority = 0
214+
else:
215+
priority = last_priority + 1
216+
217+
rule = self.create(
218+
project=project,
219+
priority=priority,
220+
description=description,
221+
match_arg=match_arg,
222+
version_type=version_type,
223+
action=action,
224+
action_arg=action_arg,
225+
)
226+
return rule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.22 on 2019-07-25 17:24
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('builds', '0009_added_external_version_type'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='versionautomationrule',
17+
name='description',
18+
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Description'),
19+
),
20+
]

readthedocs/builds/models.py

+40-28
Original file line numberDiff line numberDiff line change
@@ -17,52 +17,31 @@
1717
from polymorphic.models import PolymorphicModel
1818

1919
import readthedocs.builds.automation_actions as actions
20-
from readthedocs.config import LATEST_CONFIGURATION_VERSION
21-
from readthedocs.core.utils import broadcast
22-
from readthedocs.projects.constants import (
23-
BITBUCKET_COMMIT_URL,
24-
BITBUCKET_URL,
25-
GITHUB_BRAND,
26-
GITHUB_COMMIT_URL,
27-
GITHUB_URL,
28-
GITHUB_PULL_REQUEST_URL,
29-
GITHUB_PULL_REQUEST_COMMIT_URL,
30-
GITLAB_BRAND,
31-
GITLAB_COMMIT_URL,
32-
GITLAB_MERGE_REQUEST_URL,
33-
GITLAB_MERGE_REQUEST_COMMIT_URL,
34-
GITLAB_URL,
35-
PRIVACY_CHOICES,
36-
PRIVATE,
37-
MEDIA_TYPES,
38-
)
39-
from readthedocs.projects.models import APIProject, Project
40-
from readthedocs.projects.version_handling import determine_stable_version
41-
4220
from readthedocs.builds.constants import (
4321
BRANCH,
4422
BUILD_STATE,
4523
BUILD_STATE_FINISHED,
4624
BUILD_STATE_TRIGGERED,
4725
BUILD_TYPES,
26+
EXTERNAL,
4827
GENERIC_EXTERNAL_VERSION_NAME,
4928
GITHUB_EXTERNAL_VERSION_NAME,
5029
GITLAB_EXTERNAL_VERSION_NAME,
5130
INTERNAL,
5231
LATEST,
5332
NON_REPOSITORY_VERSIONS,
54-
EXTERNAL,
5533
STABLE,
5634
TAG,
5735
VERSION_TYPES,
5836
)
5937
from readthedocs.builds.managers import (
60-
VersionManager,
61-
InternalVersionManager,
62-
ExternalVersionManager,
6338
BuildManager,
64-
InternalBuildManager,
6539
ExternalBuildManager,
40+
ExternalVersionManager,
41+
InternalBuildManager,
42+
InternalVersionManager,
43+
VersionAutomationRuleManager,
44+
VersionManager,
6645
)
6746
from readthedocs.builds.querysets import (
6847
BuildQuerySet,
@@ -75,7 +54,27 @@
7554
get_gitlab_username_repo,
7655
)
7756
from readthedocs.builds.version_slug import VersionSlugField
78-
from readthedocs.oauth.models import RemoteRepository
57+
from readthedocs.config import LATEST_CONFIGURATION_VERSION
58+
from readthedocs.core.utils import broadcast
59+
from readthedocs.projects.constants import (
60+
BITBUCKET_COMMIT_URL,
61+
BITBUCKET_URL,
62+
GITHUB_BRAND,
63+
GITHUB_COMMIT_URL,
64+
GITHUB_PULL_REQUEST_COMMIT_URL,
65+
GITHUB_PULL_REQUEST_URL,
66+
GITHUB_URL,
67+
GITLAB_BRAND,
68+
GITLAB_COMMIT_URL,
69+
GITLAB_MERGE_REQUEST_COMMIT_URL,
70+
GITLAB_MERGE_REQUEST_URL,
71+
GITLAB_URL,
72+
MEDIA_TYPES,
73+
PRIVACY_CHOICES,
74+
PRIVATE,
75+
)
76+
from readthedocs.projects.models import APIProject, Project
77+
from readthedocs.projects.version_handling import determine_stable_version
7978

8079

8180
log = logging.getLogger(__name__)
@@ -962,6 +961,12 @@ class VersionAutomationRule(PolymorphicModel, TimeStampedModel):
962961
_('Rule priority'),
963962
help_text=_('A lower number (0) means a higher priority'),
964963
)
964+
description = models.CharField(
965+
_('Description'),
966+
max_length=255,
967+
null=True,
968+
blank=True,
969+
)
965970
match_arg = models.CharField(
966971
_('Match argument'),
967972
help_text=_('Value used for the rule to match the version'),
@@ -985,6 +990,8 @@ class VersionAutomationRule(PolymorphicModel, TimeStampedModel):
985990
choices=VERSION_TYPES,
986991
)
987992

993+
objects = VersionAutomationRuleManager()
994+
988995
class Meta:
989996
unique_together = (('project', 'priority'),)
990997
ordering = ('priority', '-modified', '-created')
@@ -1028,6 +1035,11 @@ def apply_action(self, version, match_result):
10281035
raise NotImplementedError
10291036
action(version, match_result, self.action_arg)
10301037

1038+
def get_description(self):
1039+
if self.description:
1040+
return self.description
1041+
return f'{self.get_action_display()}'
1042+
10311043
def __str__(self):
10321044
class_name = self.__class__.__name__
10331045
return (

readthedocs/rtd_tests/tests/test_automation_rules.py

+58
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,61 @@ def test_action_set_default_version(self):
125125
assert self.project.get_default_version() == LATEST
126126
assert rule.run(version) is True
127127
assert self.project.get_default_version() == version.slug
128+
129+
130+
@pytest.mark.django_db
131+
class TestAutomationRuleManager:
132+
133+
@pytest.fixture(autouse=True)
134+
def setup_method(self):
135+
self.project = get(Project)
136+
137+
def test_add_rule_regex(self):
138+
assert not self.project.automation_rules.all()
139+
140+
rule = RegexAutomationRule.objects.add_rule(
141+
project=self.project,
142+
description='First rule',
143+
match_arg='.*',
144+
version_type=TAG,
145+
action=VersionAutomationRule.ACTIVATE_VERSION_ACTION,
146+
)
147+
148+
# First rule gets added with priority 0
149+
assert self.project.automation_rules.count() == 1
150+
assert rule.priority == 0
151+
152+
# Adding a second rule
153+
rule = RegexAutomationRule.objects.add_rule(
154+
project=self.project,
155+
description='Second rule',
156+
match_arg='.*',
157+
version_type=BRANCH,
158+
action=VersionAutomationRule.ACTIVATE_VERSION_ACTION,
159+
)
160+
assert self.project.automation_rules.count() == 2
161+
assert rule.priority == 1
162+
163+
# Adding a rule with a not secuencial priority
164+
rule = get(
165+
RegexAutomationRule,
166+
description='Third rule',
167+
project=self.project,
168+
priority=9,
169+
match_arg='.*',
170+
version_type=TAG,
171+
action=VersionAutomationRule.ACTIVATE_VERSION_ACTION,
172+
)
173+
assert self.project.automation_rules.count() == 3
174+
assert rule.priority == 9
175+
176+
# Adding a new rule
177+
rule = RegexAutomationRule.objects.add_rule(
178+
project=self.project,
179+
description='Fourth rule',
180+
match_arg='.*',
181+
version_type=BRANCH,
182+
action=VersionAutomationRule.ACTIVATE_VERSION_ACTION,
183+
)
184+
assert self.project.automation_rules.count() == 4
185+
assert rule.priority == 10

0 commit comments

Comments
 (0)