Completed
Push — master ( 9ea44a...691a38 )
by Ionel Cristian
01:05
created

ci.download_latest_artifacts()   B

Complexity

Conditions 5

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 5
dl 0
loc 29
rs 8.0896
1
#!/usr/bin/env python
2
"""
3
Use the AppVeyor API to download Windows artifacts.
4
5
Taken from: https://bitbucket.org/ned/coveragepy/src/tip/ci/download_appveyor.py
6
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
7
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
8
"""
9
import argparse
10
import os
11
import requests
12
import zipfile
13
14
15
def make_auth_headers():
16
    """Make the authentication headers needed to use the Appveyor API."""
17
    path = os.path.expanduser("~/.appveyor.token")
18
    if not os.path.exists(path):
19
        raise RuntimeError(
20
            "Please create a file named `.appveyor.token` in your home directory. "
21
            "You can get the token from https://ci.appveyor.com/api-token"
22
        )
23
    with open(path) as f:
24
        token = f.read().strip()
25
26
    headers = {
27
        'Authorization': 'Bearer {}'.format(token),
28
    }
29
    return headers
30
31
32
def download_latest_artifacts(account_project, build_id):
33
    """Download all the artifacts from the latest build."""
34
    if build_id is None:
35
        url = "https://ci.appveyor.com/api/projects/{}".format(account_project)
36
    else:
37
        url = "https://ci.appveyor.com/api/projects/{}/build/{}".format(account_project, build_id)
38
    build = requests.get(url, headers=make_auth_headers()).json()
39
    jobs = build['build']['jobs']
40
    print("Build {0[build][version]}, {1} jobs: {0[build][message]}".format(build, len(jobs)))
41
42
    for job in jobs:
43
        name = job['name']
44
        print("  {0}: {1[status]}, {1[artifactsCount]} artifacts".format(name, job))
45
46
        url = "https://ci.appveyor.com/api/buildjobs/{}/artifacts".format(job['jobId'])
47
        response = requests.get(url, headers=make_auth_headers())
48
        artifacts = response.json()
49
50
        for artifact in artifacts:
51
            is_zip = artifact['type'] == "Zip"
52
            filename = artifact['fileName']
53
            print("    {0}, {1} bytes".format(filename, artifact['size']))
54
55
            url = "https://ci.appveyor.com/api/buildjobs/{}/artifacts/{}".format(job['jobId'], filename)
56
            download_url(url, filename, make_auth_headers())
57
58
            if is_zip:
59
                unpack_zipfile(filename)
60
                os.remove(filename)
61
62
63
def ensure_dirs(filename):
64
    """Make sure the directories exist for `filename`."""
65
    dirname, _ = os.path.split(filename)
66
    if dirname and not os.path.exists(dirname):
67
        os.makedirs(dirname)
68
69
70
def download_url(url, filename, headers):
71
    """Download a file from `url` to `filename`."""
72
    ensure_dirs(filename)
73
    response = requests.get(url, headers=headers, stream=True)
74
    if response.status_code == 200:
75
        with open(filename, 'wb') as f:
76
            for chunk in response.iter_content(16 * 1024):
77
                f.write(chunk)
78
    else:
79
        print("    Error downloading {}: {}".format(url, response))
80
81
82
def unpack_zipfile(filename):
83
    """Unpack a zipfile, using the names in the zip."""
84
    with open(filename, 'rb') as fzip:
85
        z = zipfile.ZipFile(fzip)
86
        for name in z.namelist():
87
            print("      extracting {}".format(name))
88
            ensure_dirs(name)
89
            z.extract(name)
90
91
parser = argparse.ArgumentParser(description='Download artifacts from AppVeyor.')
92
parser.add_argument('--id',
93
                    metavar='PROJECT_ID',
94
                    default='ionelmc/python-hunter',
95
                    help='Project ID in AppVeyor.')
96
parser.add_argument('build',
97
                    nargs='?',
98
                    metavar='BUILD_ID',
99
                    help='Build ID in AppVeyor. Eg: master-123')
100
101
if __name__ == "__main__":
102
    # import logging
103
    # logging.basicConfig(level="DEBUG")
104
    args = parser.parse_args()
105
    download_latest_artifacts(args.id, args.build)
106