Builds.start()   F
last analyzed

Complexity

Conditions 11

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 41
rs 3.1764
cc 11

How to fix   Complexity   

Complexity

Complex classes like Builds.start() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Copyright (c) Gonzalo Pena-Castellanos (@goanpeca)
4
#
5
# Licensed under the terms of the MIT License
6
# (See LICENSE.txt for details)
7
# -----------------------------------------------------------------------------
8
"""Appveyor Python Client."""
9
10
# Standard library imports
11
import json
12
import textwrap
13
14
# Third party imports
15
import requests
16
17
18
# --- Errors
19
class AppveyorError(Exception):
20
    pass
21
22
23
class AppveyorClientError(Exception):
24
    pass
25
26
27
# --- Client
28
class AppveyorClient(object):
29
    """
30
    Appveyor python client.
31
32
    https://www.appveyor.com/docs/api/
33
    """
34
35
    _HEADERS = {
36
        'Content-type': 'application/json',
37
        'User-Agent': 'Appveyor Python Client',
38
    }
39
40
    def __init__(self, token, endpoint=None):
41
        """Appveyor python client."""
42
        self._endpoint = endpoint or 'https://ci.appveyor.com/'
43
        self._session = requests.Session()
44
45
        # Groups
46
        self.users = Users(self)
47
        self.collaborators = Collaborators(self)
48
        self.roles = Roles(self)
49
        self.projects = Projects(self)
50
        self.builds = Builds(self)
51
        self.environments = Environments(self)
52
        self.deployments = Deployments(self)
53
54
        # Setup
55
        self._session.headers.update(self._HEADERS)
56
        self._authenticate(token)
57
58
    # --- Helpers
59
    def _make_url(self, url):
60
        """Create full api url."""
61
        return '{}{}'.format(self._endpoint, url)
62
63
    @staticmethod
64
    def _parse_response_contents(response):
65
        """Parse response and convert to json if possible."""
66
        status_code = response.status_code
67
        try:
68
            if status_code == 200:
69
                contents = response.json()
70
            else:
71
                contents = {}
72
        except:
73
            error = response.text.strip()
74
            if not error:
75
                error_msg = textwrap.dedent('''
76
                    Unexpected error
77
                        Possible reasons are:
78
                         - Communication with Appveyor has failed.
79
                         - Insufficient permissions.
80
                         - Invalid contents returned.
81
                    ''')[1:]
82
            contents = {
83
                'status_code': status_code,
84
                'error': error_msg,
85
            }
86
            raise AppveyorError(contents)
87
88
        if status_code == 200:
89
            return contents
90
        elif status_code == 204:
91
            return
92
        else:
93
            contents['status_code'] = status_code
94
            raise AppveyorError(contents)
95
96
    def _get(self, url, data=None, json=None):
97
        """Send GET request with given url."""
98
        response = self._session.get(self._make_url(url))
99
        return self._parse_response_contents(response)
100
101
    def _post(self, url, data=None, json=None):
102
        """Send POST request with given url and keyword args."""
103
        response = self._session.post(
104
            self._make_url(url), data=data, json=json)
105
        return self._parse_response_contents(response)
106
107
    def _put(self, url, data=None, json=None):
108
        """Send PUT request with given url."""
109
        response = self._session.put(self._make_url(url), data=data, json=json)
110
        return self._parse_response_contents(response)
111
112
    def _delete(self, url, data=None, json=None):
113
        """Send DELETE request with given url."""
114
        response = self._session.delete(self._make_url(url))
115
        return self._parse_response_contents(response)
116
117
    def _request(self, method_url, body=None, json=None):
118
        """"""
119
        method, url = method_url.split(' ')
120
        func = getattr(self, '_{}'.format(method.lower()))
121
        return func(url, data=body, json=json)
122
123
    def _authenticate(self, token):
124
        """Authenticate appveyor with bearer token."""
125
        url = '/api/roles'
126
        self._session.headers['Authorization'] = "Bearer {}".format(token)
127
        return self._get(url)
128
129
    def account_slug_for_repo(self, repo_full_name):
130
        """Return the account name and project slug for a repo full name."""
131
        projects = self.projects.get()
132
        for project in projects:
133
            if project['repositoryName'].lower() == repo_full_name.lower():
134
                account_name = project['accountName']
135
                project_slug = project['slug']
136
                break
137
138
        if account_name is None and project_slug is None:
139
            raise AppveyorError("Repository full name '{}'"
140
                                "is invalid".format(repo_full_name))
141
142
        return account_name, project_slug
143
144
145
class _Base(object):
146
    """Base entity class."""
147
148
    def __init__(self, client):
149
        """Base entity class."""
150
        self._client = client
151
152
153
class Users(_Base):
154
    """Appveyor user api methods."""
155
156
    def get(self, user_id=None):
157
        """
158
        Get users or user specified by user_id.
159
160
        https://www.appveyor.com/docs/api/team/#get-users
161
        https://www.appveyor.com/docs/api/team/#get-user
162
        """
163
        method_url = 'GET /api/users'
164
165
        if user_id:
166
            method_url += '/{user_id}'
167
168
        method_url = method_url.format(user_id=user_id)
169
        return self._client._request(method_url)
170
171
    def add(self,
172
            full_name,
173
            email,
174
            role_id,
175
            password=None,
176
            generate_password=False):
177
        """
178
        Add user.
179
180
        https://www.appveyor.com/docs/api/team/#add-user
181
        """
182
        method_url = 'POST /api/users'
183
        data = {
184
            "fullName": full_name,
185
            "email": email,
186
            "roleId": role_id,
187
            "generatePassword": generate_password,
188
        }
189
190
        if not generate_password:
191
            if password:
192
                data["password"] = password
193
                data["confirmPassword"] = password
194
            else:
195
                error_msg = 'Must provide a password if generate is Fasle'
196
                raise AppveyorClientError(error_msg)
197
        body = json.dumps(data)
198
        return self._client._request(method_url, body=body)
199
200
    def update(self, user):
201
        """
202
        Update user.
203
204
        ::
205
206
            user = {
207
               "userId": 3019,
208
               "fullName": "John Smith",
209
               "email": "[email protected]",
210
               "password": None,
211
               "roleId": 4,
212
               "successfulBuildNotification": "all",
213
               "failedBuildNotification": "all",
214
               "notifyWhenBuildStatusChangedOnly": True
215
            }
216
217
        https://www.appveyor.com/docs/api/team/#update-user
218
        """
219
        method_url = 'PUT /api/users'
220
        body = json.dumps(user)
221
        return self._client._request(method_url, body=body)
222
223
    def delete(self, user_id):
224
        """
225
        Delete user.
226
227
        https://www.appveyor.com/docs/api/team/#delete-user
228
        """
229
        method_url = 'DELETE /api/users/{user_id}'
230
        method_url = method_url.format(user_id=user_id)
231
        return self._client._request(method_url)
232
233
234
class Collaborators(_Base):
235
    """Appveyor collaborator api methods."""
236
237
    def get(self, user_id=None):
238
        """
239
        Get collaborators or collaborator specified by user id.
240
241
        https://www.appveyor.com/docs/api/team/#get-collaborators
242
        https://www.appveyor.com/docs/api/team/#get-collaborator
243
        """
244
        method_url = 'DELETE /api/users'
245
246
        if user_id:
247
            method_url += '/{user_id}'
248
249
        method_url = method_url.format(user_id=user_id)
250
        return self._client._request(method_url)
251
252
    def add(self, email, role_id):
253
        """
254
        Add collaborator.
255
256
        https://www.appveyor.com/docs/api/team/#add-collaborator
257
        """
258
        method_url = 'POST /api/collaborators'
259
        data = {
260
            "email": email,
261
            "roleId": role_id,
262
        }
263
        body = json.dumps(data)
264
        return self._client._request(method_url, body=body)
265
266
    def update(self, user_id, role_id):
267
        """
268
        Update collaborator.
269
270
        https://www.appveyor.com/docs/api/team/#update-collaborator
271
        """
272
        method_url = 'PUT /api/collaborators'
273
        data = {
274
            "userId": user_id,
275
            "roleId": role_id,
276
        }
277
        body = json.dumps(data)
278
        return self._client._request(method_url, body=body)
279
280
    def delete(self, user_id):
281
        """
282
        Delete collaborator.
283
284
        https://www.appveyor.com/docs/api/team/#delete-collaborator
285
        """
286
        method_url = 'DELETE /api/collaborators/{user_id}'
287
        method_url = method_url.format(user_id=user_id)
288
        return self._client._request(method_url)
289
290
291
class Roles(_Base):
292
    """Appveyor role api methods."""
293
294
    def get(self, role_id=None):
295
        """
296
        Get roles or role specified by role id.
297
298
        https://www.appveyor.com/docs/api/team/#get-roles
299
        """
300
        method_url = 'GET /api/roles'
301
302
        if role_id:
303
            method_url += '/{role_id}'
304
305
        return self._client._request(method_url)
306
307
    def add_role(self, name):
308
        """
309
        Add role.
310
311
        https://www.appveyor.com/docs/api/team/#add-role
312
        """
313
        method_url = 'POST /api/roles'
314
        data = {"name": name, }
315
        body = json.dumps(data)
316
        return self._client._request(method_url, body=body)
317
318
    def update_role(self, role):
319
        """
320
        Update role.
321
322
        ::
323
324
            {
325
               "roleId":3040,
326
               "name":"My Role",
327
               "isSystem":false,
328
               "created":"2014-03-18T20:12:08.4749886+00:00",
329
               "groups":[
330
                  {
331
                     "name":"Projects",
332
                     "permissions":[
333
                        {
334
                           "name":"ManageProjects",
335
                           "description":"Create, project settings",
336
                           "allowed":true
337
                        },
338
                        {
339
                           "name":"UpdateProjectSettings",
340
                           "description":"Update project settings",
341
                           "allowed":true
342
                        },
343
                        {
344
                           "name":"RunProjectBuild",
345
                           "description":"Run project builds",
346
                           "allowed":false
347
                        },
348
                        {
349
                           "name":"DeleteProjectBuilds",
350
                           "description":"Delete project builds",
351
                           "allowed":false
352
                        }
353
                     ]
354
                  },
355
                  {
356
                     "name":"Environments",
357
                     "permissions":[
358
                        {
359
                           "name":"ManageEnvironments",
360
                           "description":"Create environment settings",
361
                           "allowed":false
362
                        },
363
                        {
364
                           "name":"UpdateEnvironmentSettings",
365
                           "description":"Update environment settings",
366
                           "allowed":false
367
                        },
368
                        {
369
                           "name":"DeployToEnvironment",
370
                           "description":"Deploy to environment",
371
                           "allowed":false
372
                        }
373
                     ]
374
                  },
375
                  {
376
                     "name":"Account",
377
                     "permissions":[
378
                        {
379
                           "name":"UpdateAccountDetails",
380
                           "description":"Update account details",
381
                           "allowed":false
382
                        }
383
                     ]
384
                  },
385
                  {
386
                     "name":"Users",
387
                     "permissions":[
388
                        {
389
                           "name":"AddUser",
390
                           "description":"Add new user",
391
                           "allowed":false
392
                        },
393
                        {
394
                           "name":"UpdateUserDetails",
395
                           "description":"Update user details",
396
                           "allowed":false
397
                        },
398
                        {
399
                           "name":"DeleteUser",
400
                           "description":"Delete user",
401
                           "allowed":false
402
                        }
403
                     ]
404
                  },
405
                  {
406
                     "name":"Roles",
407
                     "permissions":[
408
                        {
409
                           "name":"AddRole",
410
                           "description":"Add new role",
411
                           "allowed":false
412
                        },
413
                        {
414
                           "name":"UpdateRoleDetails",
415
                           "description":"Update role details",
416
                           "allowed":false
417
                        },
418
                        {
419
                           "name":"DeleteRole",
420
                           "description":"Delete role",
421
                           "allowed":false
422
                        }
423
                     ]
424
                  },
425
                  {
426
                     "name":"User",
427
                     "permissions":[
428
                        {
429
                           "name":"ConfigureApiKeys",
430
                           "description":"Generate API keys",
431
                           "allowed":false
432
                        }
433
                     ]
434
                  }
435
               ]
436
            }
437
438
        https://www.appveyor.com/docs/api/team/#update-role
439
        """
440
        method_url = 'PUT /api/roles'
441
        body = json.dumps(role)
442
        return self._client._request(method_url, body=body)
443
444
    def delete_role(self, role_id):
445
        """
446
        Delete role.
447
448
        https://www.appveyor.com/docs/api/team/#delete-role
449
        """
450
        method_url = 'DELETE /api/roles/{role_id}'
451
        return self._client._request(method_url)
452
453
454
class Projects(_Base):
455
    """Appveyor project api methods."""
456
457
    def get(self):
458
        """
459
        Get projects.
460
461
        https://www.appveyor.com/docs/api/projects-builds/#get-projects
462
        """
463
        method_url = 'GET /api/projects'
464
        return self._client._request(method_url)
465
466
    def last_build(self, account_name, project_slug):
467
        """
468
        Get project last build.
469
470
        https://www.appveyor.com/docs/api/projects-builds/#get-project-last-build
471
        """
472
        method_url = 'GET /api/projects/{account_name}/{project_slug}'
473
        method_url = method_url.format(
474
            account_name=account_name, project_slug=project_slug)
475
        return self._client._request(method_url)
476
477
    def last_branch_build(self, account_name, project_slug, build_branch):
478
        """
479
        Get project last branch build.
480
481
        https://www.appveyor.com/docs/api/projects-builds/#get-project-last-branch-build
482
        """
483
        method_url = ('GET /api/projects/{account_name}/{project_slug}'
484
                      '/branch/{build_branch}')
485
        method_url = method_url.format(
486
            account_name=account_name,
487
            project_slug=project_slug,
488
            build_branch=build_branch)
489
        return self._client._request(method_url)
490
491
    def build(self, account_name, project_slug, build_version):
492
        """
493
        Get project build by version.
494
495
        https://www.appveyor.com/docs/api/projects-builds/#get-project-build-by-version
496
        """
497
        method_url = ('GET /api/projects/{account_name}/{project_slug}'
498
                      '/build/{build_version}')
499
        method_url = method_url.format(
500
            account_name=account_name,
501
            project_slug=project_slug,
502
            build_version=build_version)
503
        return self._client._request(method_url)
504
505
    def history(self,
506
                account_name,
507
                project_slug,
508
                records_per_page=50,
509
                start_build_id=None,
510
                branch=None):
511
        """
512
        Get project history.
513
514
        https://www.appveyor.com/docs/api/projects-builds/#get-project-history
515
        """
516
        method_url = ('GET /api/projects/{account_name}/{project_slug}'
517
                      '/history?recordsNumber={records_per_page}')
518
519
        if start_build_id:
520
            method_url += '&startBuildId={start_build_id}'
521
        else:
522
            start_build_id = ''
523
            method_url += '{start_build_id}'
524
525
        if branch:
526
            method_url += '&branch={branch}'
527
        else:
528
            branch = ''
529
            method_url += '{branch}'
530
531
        method_url = method_url.format(
532
            account_name=account_name,
533
            project_slug=project_slug,
534
            records_per_page=records_per_page,
535
            start_build_id=start_build_id,
536
            branch=branch)
537
        return self._client._request(method_url)
538
539
    def deployments(self, account_name, project_slug):
540
        """
541
        Get project deployments.
542
543
        https://www.appveyor.com/docs/api/projects-builds/#get-project-deployments
544
        """
545
        method_url = ('GET /api/projects/{account_name}/{project_slug}'
546
                      '/deployments')
547
        method_url = method_url.format(
548
            account_name=account_name, project_slug=project_slug)
549
        return self._client._request(method_url)
550
551
    def settings(self, account_name, project_slug):
552
        """
553
        Get project settings in YAML.
554
555
        https://www.appveyor.com/docs/api/projects-builds/#get-project-settings-in-yaml
556
        """
557
        method_url = ('GET /api/projects/{account_name}/{project_slug}'
558
                      '/settings/yaml')
559
        method_url = method_url.format(
560
            account_name=account_name, project_slug=project_slug)
561
        return self._client._request(method_url)
562
563
    def add(self, repository_provider, repository_name):
564
        """
565
        Add project.
566
567
        https://www.appveyor.com/docs/api/projects-builds/#add-project
568
        """
569
        method_url = 'POST /api/projects'
570
        providers = [
571
            'gitHub', 'bitBucket', 'vso', 'gitLab', 'kiln', 'stash', 'git',
572
            'mercurial', 'subversion'
573
        ]
574
575
        if repository_provider not in providers:
576
            error_msg = ('Invalid repository provider. Must be one of '
577
                         '{}'.format(str(providers)))
578
            raise AppveyorClientError(error_msg)
579
580
        data = {
581
            "repositoryProvider": repository_provider,
582
            "repositoryName": repository_name,
583
        }
584
585
        body = json.dumps(data)
586
        return self._client._request(method_url, body=body)
587
588
    def update(self, account_name, project_slug, project):
589
        """
590
        Update project.
591
592
        ::
593
594
            {
595
               "projectId": 43682,
596
               "accountId": 2,
597
               "accountName": "appvyr",
598
               "builds": [],
599
               "name": "demo-app",
600
               "slug": "demo-app-335",
601
               "versionFormat": "1.0.{build}",
602
               "nextBuildNumber": 1,
603
               "repositoryType": "gitHub",
604
               "repositoryScm": "git",
605
               "repositoryName": "FeodorFitsner/demo-app",
606
               "repositoryBranch": "master",
607
               "webhookId": "rca5vb5qqu",
608
               "webhookUrl": "https://ci.appveyor.com/api/github/webhook?id=r",
609
               "isPrivate": false,
610
               "ignoreAppveyorYml": False,
611
               "skipBranchesWithoutAppveyorYml": False,
612
               "configuration": {
613
                  "initScripts": [],
614
                  "includeBranches": [],
615
                  "excludeBranches": [],
616
                  "onBuildSuccessScripts": [],
617
                  "onBuildErrorScripts": [],
618
                  "patchAssemblyInfo": False,
619
                  "assemblyInfoFile": "**\\AssemblyInfo.*",
620
                  "assemblyVersionFormat": "{version}",
621
                  "assemblyFileVersionFormat": "{version}",
622
                  "assemblyInformationalVersionFormat": "{version}",
623
                  "operatingSystem": [],
624
                  "services": [],
625
                  "shallowClone": False,
626
                  "environmentVariables": [],
627
                  "environmentVariablesMatrix": [],
628
                  "installScripts": [],
629
                  "hostsEntries": [],
630
                  "buildMode": "msbuild",
631
                  "platform": [],
632
                  "configuration": [],
633
                  "packageWebApplicationProjects": False,
634
                  "packageWebApplicationProjectsXCopy": False,
635
                  "packageAzureCloudServiceProjects": False,
636
                  "packageNuGetProjects": False,
637
                  "msBuildVerbosity": "minimal",
638
                  "buildScripts": [],
639
                  "beforeBuildScripts": [],
640
                  "afterBuildScripts": [],
641
                  "testMode": "auto",
642
                  "testAssemblies": [],
643
                  "testCategories": [],
644
                  "testCategoriesMatrix": [],
645
                  "testScripts": [],
646
                  "beforeTestScripts": [],
647
                  "afterTestScripts": [],
648
                  "deployMode": "providers",
649
                  "deployments": [],
650
                  "deployScripts": [],
651
                  "beforeDeployScripts": [],
652
                  "afterDeployScripts": [],
653
                  "matrixFastFinish": False,
654
                  "matrixAllowFailures": [],
655
                  "artifacts": [],
656
                  "notifications": []
657
               },
658
               "nuGetFeed": {
659
                  "id": "demo-app-tw5iw2wk3bl1",
660
                  "name": "Project demo-app",
661
                  "publishingEnabled": False,
662
                  "created": "2014-08-16T00:52:16.9886427+00:00"
663
               },
664
               "securityDescriptor": {
665
                  "accessRightDefinitions": [
666
                     {
667
                        "name": "View",
668
                        "description": "View"
669
                     },
670
                     {
671
                        "name": "RunBuild",
672
                        "description": "Run build"
673
                     },
674
                     {
675
                        "name": "Update",
676
                        "description": "Update settings"
677
                     },
678
                     {
679
                        "name": "Delete",
680
                        "description": "Delete project"
681
                     }
682
                  ],
683
                  "roleAces": [
684
                     {
685
                        "roleId": 4,
686
                        "name": "Administrator",
687
                        "isAdmin": True,
688
                        "accessRights": [
689
                           {
690
                              "name": "View",
691
                              "allowed": True
692
                           },
693
                           {
694
                              "name": "RunBuild",
695
                              "allowed": True
696
                           },
697
                           {
698
                              "name": "Update",
699
                              "allowed": True
700
                           },
701
                           {
702
                              "name": "Delete",
703
                              "allowed": True
704
                           }
705
                        ]
706
                     },
707
                     {
708
                        "roleId": 5,
709
                        "name": "User",
710
                        "isAdmin": False,
711
                        "accessRights": [
712
                           {
713
                              "name": "View"
714
                           },
715
                           {
716
                              "name": "RunBuild"
717
                           },
718
                           {
719
                              "name": "Update"
720
                           },
721
                           {
722
                              "name": "Delete"
723
                           }
724
                        ]
725
                     }
726
                  ]
727
               },
728
               "created": "2014-08-16T00:52:15.6604826+00:00"
729
            }
730
731
        https://www.appveyor.com/docs/api/projects-builds/#update-project
732
        """
733
        method_url = ('PUT /api/projects/{account_name}/{project_slug}'
734
                      '/settings/build-number')
735
        method_url = method_url.format(
736
            account_name=account_name, project_slug=project_slug)
737
        body = json.dumps(project)
738
        return self._client._request(method_url, body=body)
739
740
    def update_settings(self, account_name, project_slug, settings):
741
        """
742
        Update project settings in YAML.
743
744
        ::
745
746
            version: 1.0.{build}
747
            build:
748
              project: MySolution.sln
749
              verbosity: minimal
750
              publish_wap: true
751
              ...
752
753
754
        https://www.appveyor.com/docs/api/projects-builds/#update-project-settings-in-yaml
755
        """
756
        method_url = ('PUT /api/projects/{account_name}/{project_slug}'
757
                      '/settings/build-number')
758
        method_url = method_url.format(
759
            account_name=account_name, project_slug=project_slug)
760
761
        body = json.dumps(settings)
762
        return self._client._request(method_url, body=body)
763
764
    def update_build_number(self, account_name, project_slug,
765
                            next_build_number):
766
        """
767
        Update project build number.
768
769
        https://www.appveyor.com/docs/api/projects-builds/#update-project-build-number
770
        """
771
        method_url = ('PUT /api/projects/{account_name}/{project_slug}'
772
                      '/settings/build-number')
773
        method_url = method_url.format(
774
            account_name=account_name, project_slug=project_slug)
775
        data = {'nextBuildNumber': next_build_number}
776
        return self._client._request(method_url, json=data)
777
778
    def delete_build_cache(self, account_name, project_slug):
779
        """
780
        Delete project build cache.
781
782
        https://www.appveyor.com/docs/api/projects-builds/#delete-project-build-cache
783
        """
784
        method_url = ('DELETE /api/projects/{account_name}/{project_slug}'
785
                      '/buildcache')
786
        method_url = method_url.format(
787
            account_name=account_name, project_slug=project_slug)
788
        return self._client._request(method_url)
789
790
    def delete(self, account_name, project_slug):
791
        """
792
        Delete project.
793
794
        https://www.appveyor.com/docs/api/projects-builds/#delete-project
795
        """
796
        method_url = 'DELETE /api/projects/{account_name}/{project_slug}'
797
        method_url = method_url.format(
798
            account_name=account_name, project_slug=project_slug)
799
        return self._client._request(method_url)
800
801
802
class Builds(_Base):
803
    """Appveyor build api methods."""
804
805
    def start(self,
806
              account_name,
807
              project_slug,
808
              branch=None,
809
              pull_request_number=None,
810
              commit=None,
811
              environment_variables={}):
812
        """
813
        Start build for branch, commit or pull request (GitHub only).
814
815
        https://www.appveyor.com/docs/api/projects-builds/#start-build-of-branch-most-recent-commit
816
        https://www.appveyor.com/docs/api/projects-builds/#start-build-of-specific-branch-commit
817
        https://www.appveyor.com/docs/api/projects-builds/#start-build-of-pull-request-github-only
818
        """
819
        method_url = 'POST /api/builds'
820
        data = {
821
            'accountName': account_name,
822
            'projectSlug': project_slug,
823
        }
824
825
        if branch and not pull_request_number and not commit:
826
            data['branch'] = branch
827
        elif commit and not branch and not pull_request_number:
828
            # 'branch' parameter is mandatory according to 'Start build of specific branch commit'.
829
            # If there is no 'branch' parameter, git clone fails with the following error.
830
            #   'fatal: Remote branch  not found in upstream origin'
831
            # It is used for the parameter of --branch option.
832
            data['branch'] = 'master'
833
            data['commitId'] = commit
834
        elif pull_request_number and not commit and not branch:
835
            data['pullRequestId'] = pull_request_number
836
        else:
837
            error_msg = ('Must provide only one of branch or one pull request '
838
                         'id or one commit id')
839
            raise AppveyorClientError(error_msg)
840
841
        if environment_variables:
842
            data['environmentVariables'] = environment_variables
843
844
        body = json.dumps(data)
845
        return self._client._request(method_url, body=body)
846
847
    def cancel(self, account_name, project_slug, build_version):
848
        """
849
        Cancel build.
850
851
        https://www.appveyor.com/docs/api/projects-builds/#cancel-build
852
        """
853
        method_url = ('DELETE /api/builds/{account_name}/{project_slug}'
854
                      '/{build_version}')
855
        method_url = method_url.format(
856
            account_name=account_name,
857
            project_slug=project_slug,
858
            build_version=build_version)
859
        return self._client._request(method_url)
860
861
    def delete(self, account_name, buildId):
862
        """
863
        Delete build.
864
865
        https://www.appveyor.com/docs/api/projects-builds/#delete-project
866
        """
867
        method_url = ('DELETE /api/builds/{buildId}')
868
        method_url = method_url.format(
869
            account_name=account_name,
870
            buildId=buildId)
871
        return self._client._request(method_url)
872
873
    def log(self, job_id):
874
        """
875
        Download build log.
876
877
        https://www.appveyor.com/docs/api/projects-builds/#download-build-log
878
        """
879
        method_url = 'GET /api/buildjobs/{job_id}/log'
880
        method_url = method_url.format(job_id=job_id)
881
        return self._client._request(method_url)
882
883
884
class Environments(_Base):
885
    """
886
    Appveyor environment api methods.
887
888
    https://www.appveyor.com/docs/api/environments-deployments/#environments
889
    """
890
891
    def get(self):
892
        """
893
        Get environments.
894
895
        https://www.appveyor.com/docs/api/environments-deployments/#get-environments
896
        """
897
        method_url = 'GET /api/environments'
898
        return self._client._request(method_url)
899
900
    def settings(self, deployment_environment_id):
901
        """
902
        Get environment settings.
903
904
        https://www.appveyor.com/docs/api/environments-deployments/#get-environment-settings
905
        """
906
        method_url = ('GET /api/environments/'
907
                      '{deployment_environment_id}/settings')
908
        method_url = method_url.format(
909
            deployment_environment_id=deployment_environment_id, )
910
        return self._client._request(method_url)
911
912
    def deployments(self, deployment_environment_id):
913
        """
914
        Get environment deployments.
915
916
        https://www.appveyor.com/docs/api/environments-deployments/#get-environment-deployments
917
        """
918
        method_url = ('GET /api/environments/'
919
                      '{deployment_environment_id}/deployments')
920
        method_url = method_url.format(
921
            deployment_environment_id=deployment_environment_id, )
922
        return self._client._request(method_url)
923
924
    def add(self, environment):
925
        """
926
        Add environment.
927
928
        ::
929
930
            example_environment = {
931
               "name": "production",
932
               "provider": "FTP",
933
               "settings": {
934
                  "providerSettings": [
935
                     {
936
                        "name":"server",
937
                        "value": {
938
                           "value": "ftp.myserver.com",
939
                           "isEncrypted": False
940
                        }
941
                     },
942
                     {
943
                        "name": "username",
944
                        "value": {
945
                           "value": "ftp-user",
946
                           "isEncrypted": False
947
                        }
948
                     },
949
                     {
950
                        "name": "password",
951
                        "value": {
952
                           "value": "password",
953
                           "isEncrypted": True
954
                        }
955
                     }
956
                  ],
957
                  "environmentVariables": [
958
                     {
959
                        "name": "my-var",
960
                        "value": {
961
                           "value": "123",
962
                           "isEncrypted": False
963
                        }
964
                     }
965
                  ]
966
               }
967
            }
968
969
        https://www.appveyor.com/docs/api/environments-deployments/#add-environment
970
        """
971
        method_url = 'POST /api/environments'
972
        body = json.dumps(environment)
973
        return self._client._request(method_url, body=body)
974
975
    def update(self, environment):
976
        """
977
978
        ::
979
            {
980
               "deploymentEnvironmentId": 3018,
981
               "name": "production",
982
               "environmentAccessKey": "gi3ttevuk7123",
983
               "settings": {
984
                  "providerSettings": [
985
                     {
986
                        "name": "server",
987
                        "value": {
988
                           "isEncrypted": False,
989
                           "value": "ftp.myserver.com"
990
                        }
991
                     },
992
                     {
993
                        "name": "username",
994
                        "value": {
995
                           "isEncrypted": False,
996
                           "value": "ftp-user"
997
                        }
998
                     },
999
                     {
1000
                        "name": "password",
1001
                        "value": {
1002
                           "isEncrypted": True,
1003
                           "value": "password"
1004
                        }
1005
                     }
1006
                  ],
1007
                  "environmentVariables": [
1008
                     {
1009
                        "name": "my-var",
1010
                        "value": {
1011
                           "isEncrypted": False,
1012
                           "value": "123"
1013
                        }
1014
                     }
1015
                  ],
1016
                  "provider": "FTP"
1017
               }
1018
            }
1019
1020
        https://www.appveyor.com/docs/api/environments-deployments/#update-environment
1021
        """
1022
        method_url = 'PUT /api/environments'
1023
        body = json.dumps(environment)
1024
        return self._client._request(method_url, body=body)
1025
1026
    def delete(self, deployment_environment_id):
1027
        """
1028
        Delete environment
1029
1030
        https://www.appveyor.com/docs/api/environments-deployments/#delete-environment
1031
        """
1032
        method_url = 'DELETE /api/environments/{deployment_environment_id}'
1033
        method_url = method_url.format(
1034
            deployment_environment_id=deployment_environment_id, )
1035
        return self._client._request(method_url)
1036
1037
1038
class Deployments(_Base):
1039
    """
1040
    Appveyor deployment api methods.
1041
1042
    https://www.appveyor.com/docs/api/environments-deployments/#deployments
1043
    """
1044
1045
    def get(self, deployment_id):
1046
        """
1047
        Get deployment.
1048
1049
        https://www.appveyor.com/docs/api/environments-deployments/#get-deployment
1050
        """
1051
        method_url = 'GET /api/deployments/{deployment_id}'
1052
        method_url = method_url.format(deployment_id=deployment_id)
1053
        return self._client._request(method_url)
1054
1055
    def start(self,
1056
              account_name,
1057
              project_slug,
1058
              environment_name,
1059
              build_version,
1060
              build_job_id=None,
1061
              environment_variables={}):
1062
        """
1063
        Start deployment.
1064
1065
        https://www.appveyor.com/docs/api/environments-deployments/#start-deployment
1066
        """
1067
        method_url = 'POST /api/deployments'
1068
        data = {
1069
            "environmentName": environment_name,
1070
            "accountName": account_name,
1071
            "projectSlug": project_slug,
1072
            "buildVersion": build_version,  # Build to deploy
1073
            "environmentVariables": environment_variables
1074
        }
1075
1076
        # Optional job id with artifacts if build contains multiple jobs
1077
        if build_job_id:
1078
            data["buildJobId"] = build_job_id
1079
1080
        body = json.dumps(data)
1081
        return self._client._request(method_url, body=body)
1082
1083
    def cancel(self, deployment_id):
1084
        """
1085
        Cancel deployment.
1086
1087
        https://www.appveyor.com/docs/api/environments-deployments/#cancel-deployment
1088
        """
1089
        method_url = 'PUT /api/deployments/stop'
1090
        data = {"deploymentId": deployment_id}
1091
        body = json.dumps(data)
1092
        return self._client._request(method_url, body=body)
1093