/
hooks.py
177 lines (144 loc) · 5.22 KB
/
hooks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"""Views pertaining to builds."""
import logging
from readthedocs.builds.constants import EXTERNAL
from readthedocs.core.utils import trigger_build
from readthedocs.projects.tasks import sync_repository_task
log = logging.getLogger(__name__)
def _build_version(project, slug, already_built=()):
"""
Where we actually trigger builds for a project and slug.
All webhook logic should route here to call ``trigger_build``.
"""
if not project.has_valid_webhook:
project.has_valid_webhook = True
project.save()
# Previously we were building the latest version (inactive or active)
# when building the default version,
# some users may have relied on this to update the version list #4450
version = project.versions.filter(active=True, slug=slug).first()
if version and slug not in already_built:
log.info(
'(Version build) Building %s:%s',
project.slug,
version.slug,
)
trigger_build(project=project, version=version, force=True)
return slug
log.info('(Version build) Not Building %s', slug)
return None
def build_branches(project, branch_list):
"""
Build the branches for a specific project.
Returns:
to_build - a list of branches that were built
not_building - a list of branches that we won't build
"""
to_build = set()
not_building = set()
for branch in branch_list:
versions = project.versions_from_branch_name(branch)
for version in versions:
log.info(
'(Branch Build) Processing %s:%s',
project.slug,
version.slug,
)
ret = _build_version(project, version.slug, already_built=to_build)
if ret:
to_build.add(ret)
else:
not_building.add(version.slug)
return (to_build, not_building)
def sync_versions(project):
"""
Sync the versions of a repo using its latest version.
This doesn't register a new build,
but clones the repo and syncs the versions.
Due that `sync_repository_task` is bound to a version,
we always pass the default version.
:returns: The version slug that was used to trigger the clone.
:rtype: str
"""
try:
version_identifier = project.get_default_branch()
version = (
project.versions.filter(
identifier=version_identifier,
).first()
)
if not version:
log.info('Unable to sync from %s version', version_identifier)
return None
sync_repository_task.delay(version.pk)
return version.slug
except Exception:
log.exception('Unknown sync versions exception')
return None
def get_or_create_external_version(project, identifier, verbose_name):
"""
Get or create external versions using `identifier` and `verbose_name`.
if external version does not exist create an external version
:param project: Project instance
:param identifier: Commit Hash
:param verbose_name: pull/merge request number
:returns: External version.
:rtype: Version
"""
external_version, created = project.versions.get_or_create(
verbose_name=verbose_name,
type=EXTERNAL,
defaults={'identifier': identifier, 'active': True},
)
if created:
log.info(
'(Create External Version) Added Version: [%s] ',
external_version.slug
)
else:
# identifier will change if there is a new commit to the Pull/Merge Request
if external_version.identifier != identifier:
external_version.identifier = identifier
external_version.save()
log.info(
'(Update External Version) Updated Version: [%s] ',
external_version.slug
)
return external_version
def delete_external_version(project, identifier, verbose_name):
"""
Delete external versions using `identifier` and `verbose_name`.
if external version does not exist then returns `None`.
:param project: Project instance
:param identifier: Commit Hash
:param verbose_name: pull/merge request number
:returns: verbose_name (pull/merge request number).
:rtype: str
"""
external_version = project.versions(manager=EXTERNAL).filter(
verbose_name=verbose_name, identifier=identifier
).first()
if external_version:
# Delete External Version
external_version.delete()
log.info(
'(Delete External Version) Deleted Version: [%s]',
external_version.slug
)
return external_version.verbose_name
return None
def build_external_version(project, version, commit):
"""
Where we actually trigger builds for external versions.
All pull/merge request webhook logic should route here to call ``trigger_build``.
"""
if not project.has_valid_webhook:
project.has_valid_webhook = True
project.save()
# Build External version
log.info(
'(External Version build) Building %s:%s',
project.slug,
version.slug,
)
trigger_build(project=project, version=version, commit=commit, force=True)
return version.verbose_name