]>
Commit | Line | Data |
---|---|---|
db56f281 S |
1 | #!/usr/bin/env python |
2 | from __future__ import unicode_literals | |
3 | ||
689f31fd | 4 | import io |
db56f281 S |
5 | import json |
6 | import mimetypes | |
7 | import netrc | |
8 | import optparse | |
9 | import os | |
689f31fd | 10 | import re |
db56f281 S |
11 | import sys |
12 | ||
13 | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
14 | ||
cefecac1 | 15 | from youtube_dlc.compat import ( |
db56f281 | 16 | compat_basestring, |
db56f281 S |
17 | compat_getpass, |
18 | compat_print, | |
19 | compat_urllib_request, | |
20 | ) | |
cefecac1 | 21 | from youtube_dlc.utils import ( |
db56f281 S |
22 | make_HTTPS_handler, |
23 | sanitized_Request, | |
24 | ) | |
25 | ||
26 | ||
27 | class GitHubReleaser(object): | |
067aa17e S |
28 | _API_URL = 'https://api.github.com/repos/ytdl-org/youtube-dl/releases' |
29 | _UPLOADS_URL = 'https://uploads.github.com/repos/ytdl-org/youtube-dl/releases/%s/assets?name=%s' | |
db56f281 S |
30 | _NETRC_MACHINE = 'github.com' |
31 | ||
32 | def __init__(self, debuglevel=0): | |
33 | self._init_github_account() | |
34 | https_handler = make_HTTPS_handler({}, debuglevel=debuglevel) | |
35 | self._opener = compat_urllib_request.build_opener(https_handler) | |
36 | ||
37 | def _init_github_account(self): | |
38 | try: | |
39 | info = netrc.netrc().authenticators(self._NETRC_MACHINE) | |
40 | if info is not None: | |
0d5c415e | 41 | self._token = info[2] |
db56f281 S |
42 | compat_print('Using GitHub credentials found in .netrc...') |
43 | return | |
44 | else: | |
45 | compat_print('No GitHub credentials found in .netrc') | |
46 | except (IOError, netrc.NetrcParseError): | |
47 | compat_print('Unable to parse .netrc') | |
0d5c415e S |
48 | self._token = compat_getpass( |
49 | 'Type your GitHub PAT (personal access token) and press [Return]: ') | |
db56f281 S |
50 | |
51 | def _call(self, req): | |
52 | if isinstance(req, compat_basestring): | |
53 | req = sanitized_Request(req) | |
0d5c415e | 54 | req.add_header('Authorization', 'token %s' % self._token) |
db56f281 S |
55 | response = self._opener.open(req).read().decode('utf-8') |
56 | return json.loads(response) | |
57 | ||
58 | def list_releases(self): | |
59 | return self._call(self._API_URL) | |
60 | ||
61 | def create_release(self, tag_name, name=None, body='', draft=False, prerelease=False): | |
62 | data = { | |
63 | 'tag_name': tag_name, | |
64 | 'target_commitish': 'master', | |
65 | 'name': name, | |
66 | 'body': body, | |
67 | 'draft': draft, | |
68 | 'prerelease': prerelease, | |
69 | } | |
70 | req = sanitized_Request(self._API_URL, json.dumps(data).encode('utf-8')) | |
71 | return self._call(req) | |
72 | ||
73 | def create_asset(self, release_id, asset): | |
74 | asset_name = os.path.basename(asset) | |
75 | url = self._UPLOADS_URL % (release_id, asset_name) | |
76 | # Our files are small enough to be loaded directly into memory. | |
77 | data = open(asset, 'rb').read() | |
78 | req = sanitized_Request(url, data) | |
79 | mime_type, _ = mimetypes.guess_type(asset_name) | |
80 | req.add_header('Content-Type', mime_type or 'application/octet-stream') | |
81 | return self._call(req) | |
82 | ||
83 | ||
84 | def main(): | |
689f31fd | 85 | parser = optparse.OptionParser(usage='%prog CHANGELOG VERSION BUILDPATH') |
db56f281 | 86 | options, args = parser.parse_args() |
689f31fd | 87 | if len(args) != 3: |
db56f281 S |
88 | parser.error('Expected a version and a build directory') |
89 | ||
689f31fd S |
90 | changelog_file, version, build_path = args |
91 | ||
92 | with io.open(changelog_file, encoding='utf-8') as inf: | |
93 | changelog = inf.read() | |
94 | ||
95 | mobj = re.search(r'(?s)version %s\n{2}(.+?)\n{3}' % version, changelog) | |
96 | body = mobj.group(1) if mobj else '' | |
db56f281 | 97 | |
db59b37d | 98 | releaser = GitHubReleaser() |
db56f281 | 99 | |
689f31fd | 100 | new_release = releaser.create_release( |
cefecac1 | 101 | version, name='youtube-dlc %s' % version, body=body) |
db56f281 S |
102 | release_id = new_release['id'] |
103 | ||
104 | for asset in os.listdir(build_path): | |
105 | compat_print('Uploading %s...' % asset) | |
106 | releaser.create_asset(release_id, os.path.join(build_path, asset)) | |
107 | ||
108 | ||
109 | if __name__ == '__main__': | |
110 | main() |