Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 # coding: utf-8 | 1 # coding: utf-8 |
2 | 2 |
3 # This file is part of the Adblock Plus web scripts, | 3 # This file is part of the Adblock Plus web scripts, |
4 # Copyright (C) 2006-2015 Eyeo GmbH | 4 # Copyright (C) 2006-2015 Eyeo GmbH |
5 # | 5 # |
6 # Adblock Plus is free software: you can redistribute it and/or modify | 6 # Adblock Plus is free software: you can redistribute it and/or modify |
7 # it under the terms of the GNU General Public License version 3 as | 7 # it under the terms of the GNU General Public License version 3 as |
8 # published by the Free Software Foundation. | 8 # published by the Free Software Foundation. |
9 # | 9 # |
10 # Adblock Plus is distributed in the hope that it will be useful, | 10 # Adblock Plus is distributed in the hope that it will be useful, |
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 # GNU General Public License for more details. | 13 # GNU General Public License for more details. |
14 # | 14 # |
15 # You should have received a copy of the GNU General Public License | 15 # You should have received a copy of the GNU General Public License |
16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 |
18 """ | 18 """ |
19 | 19 |
20 Nightly builds generation script | 20 Nightly builds generation script |
21 ================================ | 21 ================================ |
22 | 22 |
23 This script generates nightly builds of extensions, together | 23 This script generates nightly builds of extensions, together |
24 with changelogs and documentation. | 24 with changelogs and documentation. |
25 | 25 |
26 """ | 26 """ |
27 | 27 |
28 import sys, os, os.path, subprocess, ConfigParser, json, hashlib | 28 import ConfigParser |
Felix Dahlke
2015/08/13 12:52:27
Nit: Might be a good opportunity to clean the comm
Wladimir Palant
2015/08/13 13:00:40
As I said, I intentionally didn't clean up the imp
| |
29 import tempfile, shutil, urlparse, pipes, time, urllib2, struct | |
30 import cookielib | 29 import cookielib |
30 from datetime import datetime | |
31 import hashlib | |
31 import HTMLParser | 32 import HTMLParser |
33 import json | |
32 import logging | 34 import logging |
33 from datetime import datetime | 35 import os |
36 import pipes | |
37 import shutil | |
38 import struct | |
39 import subprocess | |
40 import sys | |
41 import tempfile | |
42 import time | |
34 from urllib import urlencode | 43 from urllib import urlencode |
44 import urllib2 | |
45 import urlparse | |
35 from xml.dom.minidom import parse as parseXml | 46 from xml.dom.minidom import parse as parseXml |
36 from sitescripts.utils import get_config, get_template | 47 |
37 from sitescripts.extensions.utils import ( | 48 from sitescripts.extensions.utils import ( |
38 compareVersions, Configuration, | 49 compareVersions, Configuration, |
39 writeAndroidUpdateManifest | 50 writeAndroidUpdateManifest |
40 ) | 51 ) |
52 from sitescripts.utils import get_config, get_template | |
41 | 53 |
42 MAX_BUILDS = 50 | 54 MAX_BUILDS = 50 |
43 | 55 |
44 | 56 |
45 class NightlyBuild(object): | 57 class NightlyBuild(object): |
46 """ | 58 """ |
47 Performs the build process for an extension, | 59 Performs the build process for an extension, |
48 generating changelogs and documentation. | 60 generating changelogs and documentation. |
49 """ | 61 """ |
50 | 62 |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 password = get_config().get('extensions', 'amo_password') | 396 password = get_config().get('extensions', 'amo_password') |
385 | 397 |
386 slug = self.config.galleryID | 398 slug = self.config.galleryID |
387 login_url= 'https://addons.mozilla.org/en-US/firefox/users/login' | 399 login_url= 'https://addons.mozilla.org/en-US/firefox/users/login' |
388 upload_url = 'https://addons.mozilla.org/en-US/developers/addon/%s/upload' % slug | 400 upload_url = 'https://addons.mozilla.org/en-US/developers/addon/%s/upload' % slug |
389 add_url = 'https://addons.mozilla.org/en-US/developers/addon/%s/versions/add ' % slug | 401 add_url = 'https://addons.mozilla.org/en-US/developers/addon/%s/versions/add ' % slug |
390 | 402 |
391 cookie_jar = cookielib.CookieJar() | 403 cookie_jar = cookielib.CookieJar() |
392 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie_jar)) | 404 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie_jar)) |
393 | 405 |
394 def load_url(url, data=None): | 406 def load_url(url, data=None): |
Sebastian Noack
2015/08/12 13:29:26
Any reason, why you don'T simply use urllib3.reque
Wladimir Palant
2015/08/12 13:34:10
Yes, urllib3 doesn't support cookie jars.
| |
395 content_type = 'application/x-www-form-urlencoded' | 407 content_type = 'application/x-www-form-urlencoded' |
396 if isinstance(data, dict): | 408 if isinstance(data, dict): |
397 if any(isinstance(v, tuple) for v in data.itervalues()): | 409 if any(isinstance(v, tuple) for v in data.itervalues()): |
398 data, content_type = urllib3.filepost.encode_multipart_formdata(data) | 410 data, content_type = urllib3.filepost.encode_multipart_formdata(data) |
399 else: | 411 else: |
400 data = urlencode(data.items()) | 412 data = urlencode(data.items()) |
401 | 413 |
402 request = urllib2.Request(url, data, headers={'Content-Type': content_type }) | 414 request = urllib2.Request(url, data, headers={'Content-Type': content_type }) |
403 response = opener.open(request) | 415 response = opener.open(request) |
404 try: | 416 try: |
405 return response.read() | 417 return response.read() |
406 finally: | 418 finally: |
407 response.close() | 419 response.close() |
408 | 420 |
409 class CSRFParser(HTMLParser.HTMLParser): | 421 class CSRFParser(HTMLParser.HTMLParser): |
Sebastian Noack
2015/08/12 13:29:26
Don't we already use minidom somewhere else? That
Wladimir Palant
2015/08/12 13:34:10
Does minidom parse HTML? Not that I know.
Felix Dahlke
2015/08/13 12:52:27
I've used BeautifulSoup for this kind of stuff. Bu
Sebastian Noack
2015/08/18 09:04:13
Alright, minidom is only for XML, though it also w
| |
410 result = None | 422 result = None |
411 dummy_exception = Exception() | 423 dummy_exception = Exception() |
412 | 424 |
413 def __init__(self, data): | 425 def __init__(self, data): |
414 HTMLParser.HTMLParser.__init__(self) | 426 HTMLParser.HTMLParser.__init__(self) |
415 try: | 427 try: |
416 self.feed(data) | 428 self.feed(data) |
417 self.close() | 429 self.close() |
418 except Exception, e: | 430 except Exception, e: |
419 if e != self.dummy_exception: | 431 if e != self.dummy_exception: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 upload_response = json.loads(load_url( | 465 upload_response = json.loads(load_url( |
454 upload_url, | 466 upload_url, |
455 { | 467 { |
456 'csrfmiddlewaretoken': csrf_token, | 468 'csrfmiddlewaretoken': csrf_token, |
457 'upload': (os.path.basename(self.path), file.read(), 'application/x-xp install'), | 469 'upload': (os.path.basename(self.path), file.read(), 'application/x-xp install'), |
458 } | 470 } |
459 )) | 471 )) |
460 | 472 |
461 # Wait for validation to finish | 473 # Wait for validation to finish |
462 while not upload_response.get('validation'): | 474 while not upload_response.get('validation'): |
463 time.sleep(2) | 475 time.sleep(2) |
Sebastian Noack
2015/08/12 13:29:26
I suppose there is no way to get notified when it'
Wladimir Palant
2015/08/12 13:34:10
No, it's exactly how the web interface does it - b
| |
464 upload_response = json.loads(load_url( | 476 upload_response = json.loads(load_url( |
465 upload_url + '/' + upload_response.get('upload') | 477 upload_url + '/' + upload_response.get('upload') |
466 )) | 478 )) |
467 | 479 |
468 if upload_response['validation'].get('errors', 0): | 480 if upload_response['validation'].get('errors', 0): |
Sebastian Noack
2015/08/12 13:29:26
Nit: Omit the default value? None evaluates to Fal
Wladimir Palant
2015/08/12 13:34:10
Yes, I considered it but the default value indicat
| |
469 raise Exception('Build failed AMO validation, see https://addons.mozilla.o rg%s' % upload_response.get('full_report_url')) | 481 raise Exception('Build failed AMO validation, see https://addons.mozilla.o rg%s' % upload_response.get('full_report_url')) |
470 | 482 |
471 # Add version | 483 # Add version |
472 add_response = json.loads(load_url( | 484 add_response = json.loads(load_url( |
473 add_url, | 485 add_url, |
474 { | 486 { |
475 'csrfmiddlewaretoken': csrf_token, | 487 'csrfmiddlewaretoken': csrf_token, |
476 'upload': upload_response.get('upload'), | 488 'upload': upload_response.get('upload'), |
477 'source': ('', '', 'application/octet-stream'), | 489 'source': ('', '', 'application/octet-stream'), |
478 'beta': 'on', | 490 'beta': 'on', |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
565 self.readSafariMetadata() | 577 self.readSafariMetadata() |
566 else: | 578 else: |
567 self.readGeckoMetadata() | 579 self.readGeckoMetadata() |
568 | 580 |
569 # create development build | 581 # create development build |
570 self.build() | 582 self.build() |
571 | 583 |
572 # write out changelog | 584 # write out changelog |
573 self.writeChangelog(self.getChanges()) | 585 self.writeChangelog(self.getChanges()) |
574 | 586 |
575 # write update.rdf file | 587 # write update manifest |
576 self.writeUpdateManifest() | 588 if self.config.type != 'gecko': |
589 self.writeUpdateManifest() | |
577 | 590 |
578 # update documentation | 591 # update documentation |
579 self.updateDocs() | 592 self.updateDocs() |
580 | 593 |
581 # retire old builds | 594 # retire old builds |
582 versions = self.retireBuilds() | 595 versions = self.retireBuilds() |
583 | 596 |
584 if self.config.type == 'ie': | 597 if self.config.type == 'ie': |
585 self.writeIEUpdateManifest(versions) | 598 self.writeIEUpdateManifest(versions) |
586 | 599 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
621 except Exception, ex: | 634 except Exception, ex: |
622 logging.error("The build for %s failed:", repo) | 635 logging.error("The build for %s failed:", repo) |
623 logging.exception(ex) | 636 logging.exception(ex) |
624 | 637 |
625 file = open(nightlyConfigFile, 'wb') | 638 file = open(nightlyConfigFile, 'wb') |
626 nightlyConfig.write(file) | 639 nightlyConfig.write(file) |
627 | 640 |
628 | 641 |
629 if __name__ == '__main__': | 642 if __name__ == '__main__': |
630 main() | 643 main() |
LEFT | RIGHT |