3
3
import hashlib
4
4
import hmac
5
5
import json
6
- import structlog
7
6
import re
7
+ from functools import namedtuple
8
8
9
+ import structlog
9
10
from django .shortcuts import get_object_or_404
10
11
from rest_framework import permissions , status
11
12
from rest_framework .exceptions import NotFound , ParseError
14
15
from rest_framework .status import HTTP_400_BAD_REQUEST
15
16
from rest_framework .views import APIView
16
17
17
- from readthedocs .core .signals import (
18
- webhook_bitbucket ,
19
- webhook_github ,
20
- webhook_gitlab ,
21
- )
18
+ from readthedocs .core .signals import webhook_bitbucket , webhook_github , webhook_gitlab
22
19
from readthedocs .core .views .hooks import (
23
20
build_branches ,
24
21
build_external_version ,
27
24
trigger_sync_versions ,
28
25
)
29
26
from readthedocs .integrations .models import HttpExchange , Integration
30
- from readthedocs .projects .models import Feature , Project
27
+ from readthedocs .projects .models import Project
31
28
32
29
log = structlog .get_logger (__name__ )
33
30
55
52
BITBUCKET_PUSH = 'repo:push'
56
53
57
54
55
+ ExternalVersionData = namedtuple (
56
+ "ExternalVersionData" ,
57
+ ["id" , "source_branch" , "base_branch" , "commit" ],
58
+ )
59
+
60
+
58
61
class WebhookMixin :
59
62
60
63
"""Base class for Webhook mixins."""
@@ -228,20 +231,22 @@ def get_external_version_response(self, project):
228
231
:param project: Project instance
229
232
:type project: readthedocs.projects.models.Project
230
233
"""
231
- identifier , verbose_name = self .get_external_version_data ()
234
+ version_data = self .get_external_version_data ()
232
235
# create or get external version object using `verbose_name`.
233
236
external_version = get_or_create_external_version (
234
- project , identifier , verbose_name
237
+ project = project ,
238
+ version_data = version_data ,
235
239
)
236
240
# returns external version verbose_name (pull/merge request number)
237
241
to_build = build_external_version (
238
- project = project , version = external_version , commit = identifier
242
+ project = project ,
243
+ version = external_version ,
239
244
)
240
245
241
246
return {
242
- ' build_triggered' : True ,
243
- ' project' : project .slug ,
244
- ' versions' : [to_build ],
247
+ " build_triggered" : bool ( to_build ) ,
248
+ " project" : project .slug ,
249
+ " versions" : [to_build ] if to_build else [ ],
245
250
}
246
251
247
252
def get_deactivated_external_version_response (self , project ):
@@ -259,9 +264,10 @@ def get_deactivated_external_version_response(self, project):
259
264
:param project: Project instance
260
265
:type project: Project
261
266
"""
262
- identifier , verbose_name = self .get_external_version_data ()
267
+ version_data = self .get_external_version_data ()
263
268
deactivated_version = deactivate_external_version (
264
- project , identifier , verbose_name
269
+ project = project ,
270
+ version_data = version_data ,
265
271
)
266
272
return {
267
273
'version_deactivated' : bool (deactivated_version ),
@@ -320,13 +326,16 @@ def get_data(self):
320
326
def get_external_version_data (self ):
321
327
"""Get Commit Sha and pull request number from payload."""
322
328
try :
323
- identifier = self .data ['pull_request' ]['head' ]['sha' ]
324
- verbose_name = str (self .data ['number' ])
325
-
326
- return identifier , verbose_name
327
-
328
- except KeyError :
329
- raise ParseError ('Parameters "sha" and "number" are required' )
329
+ data = ExternalVersionData (
330
+ id = str (self .data ["number" ]),
331
+ commit = self .data ["pull_request" ]["head" ]["sha" ],
332
+ source_branch = self .data ["pull_request" ]["head" ]["ref" ],
333
+ base_branch = self .data ["pull_request" ]["base" ]["ref" ],
334
+ )
335
+ return data
336
+ except KeyError as e :
337
+ key = e .args [0 ]
338
+ raise ParseError (f"Invalid payload. { key } is required." )
330
339
331
340
def is_payload_valid (self ):
332
341
"""
@@ -523,13 +532,16 @@ def is_payload_valid(self):
523
532
def get_external_version_data (self ):
524
533
"""Get commit SHA and merge request number from payload."""
525
534
try :
526
- identifier = self .data ['object_attributes' ]['last_commit' ]['id' ]
527
- verbose_name = str (self .data ['object_attributes' ]['iid' ])
528
-
529
- return identifier , verbose_name
530
-
531
- except KeyError :
532
- raise ParseError ('Parameters "id" and "iid" are required' )
535
+ data = ExternalVersionData (
536
+ id = str (self .data ["object_attributes" ]["iid" ]),
537
+ commit = self .data ["object_attributes" ]["last_commit" ]["id" ],
538
+ source_branch = self .data ["object_attributes" ]["source_branch" ],
539
+ base_branch = self .data ["object_attributes" ]["target_branch" ],
540
+ )
541
+ return data
542
+ except KeyError as e :
543
+ key = e .args [0 ]
544
+ raise ParseError (f"Invalid payload. { key } is required." )
533
545
534
546
def handle_webhook (self ):
535
547
"""
0 commit comments