Skip to content

Commit

Permalink
Bug 1560713 - Move to Google API v3
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanLorenzo committed Jul 4, 2019
1 parent dfd757f commit f15ac8b
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 86 deletions.
23 changes: 12 additions & 11 deletions mozapkpublisher/check_rollout.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env python3

import argparse
import calendar
import email.utils as eu
import logging
Expand All @@ -9,18 +8,18 @@
import requests

from argparse import ArgumentParser
from mozapkpublisher.common import googleplay
from mozapkpublisher.common.googleplay import EditService, add_general_google_play_arguments


DAY = 24 * 60 * 60

logger = logging.getLogger(__name__)


def check_rollout(edits_service, package_name, days):
def check_rollout(edit_service, days):
"""Check if package_name has a release on staged rollout for too long"""
edit = edits_service.insert(body={}, packageName=package_name).execute()
response = edits_service.tracks().get(editId=edit['id'], track='production', packageName=package_name).execute()
releases = response['releases']
track_status = edit_service.get_track_status(track='production')
releases = track_status['releases']
for release in releases:
if release['status'] == 'inProgress':
url = 'https://archive.mozilla.org/pub/mobile/releases/{}/SHA512SUMS'.format(release['name'])
Expand All @@ -36,15 +35,17 @@ def check_rollout(edits_service, package_name, days):

def main():
parser = ArgumentParser(description='Check for in-progress Firefox for Android staged rollout')
parser.add_argument('service_account', help='The service account email')
parser.add_argument('credentials', help='The p12 authentication file', type=argparse.FileType(mode='rb'))
add_general_google_play_arguments(parser)
parser.add_argument('--days', help='The time before we warn about incomplete staged rollout of a release (default: 7)',
type=int, default=7)
config = parser.parse_args()

# TODO: use googleplay.EditService when that is ported to v3
service = googleplay.connect(config.service_account, config.credentials.name, 'v3').edits()
for (release, age) in check_rollout(service, 'org.mozilla.firefox', config.days):
edit_service = EditService(
config.service_account,
config.google_play_credentials_file.name,
package_name='org.mozilla.firefox',
)
for (release, age) in check_rollout(edit_service, config.days):
print('fennec {} is on staged rollout at {}% but it shipped {} days ago'.format(
release['name'], int(release['userFraction'] * 100), int(age / DAY)))

Expand Down
23 changes: 18 additions & 5 deletions mozapkpublisher/common/googleplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class EditService(object):
def __init__(self, service_account, credentials_file_path, package_name, commit=False, contact_google_play=True):
self._contact_google_play = contact_google_play
if self._contact_google_play:
general_service = connect(service_account, credentials_file_path)
general_service = _connect(service_account, credentials_file_path)
self._service = general_service.edits()
else:
self._service = _craft_google_play_service_mock()
Expand Down Expand Up @@ -79,9 +79,17 @@ def commit_transaction(self):

self._edit_id = None

@transaction_required
def get_track_status(self, track):
response = self._service.tracks().get(
editId=self._edit_id, track=track, packageName=self._package_name
).execute()
logger.debug(u'Track "{}" has status: {}'.format(track, response))
return response

@transaction_required
def upload_apk(self, apk_path):
logger.info('Uploading "{}"'.format(apk_path))
logger.info('Uploading "{}"...'.format(apk_path))
try:
response = self._service.apks().upload(
editId=self._edit_id,
Expand Down Expand Up @@ -109,7 +117,12 @@ def upload_apk(self, apk_path):

@transaction_required
def update_track(self, track, version_codes, rollout_percentage=None):
body = {u'versionCodes': version_codes}
body = {
u'releases': [{
u'status': 'completed',
u'versionCodes': version_codes,
}],
}
if rollout_percentage is not None:
if rollout_percentage < 0 or rollout_percentage > 100:
raise WrongArgumentGiven('rollout percentage must be between 0 and 100. Value given: {}'.format(rollout_percentage))
Expand Down Expand Up @@ -174,7 +187,7 @@ def execute(self):
return self._return_value


def connect(service_account, credentials_file_path, api_version='v2'):
def _connect(service_account, credentials_file_path):
""" Connect to the google play interface
"""

Expand All @@ -188,6 +201,6 @@ def connect(service_account, credentials_file_path, api_version='v2'):
http = httplib2.Http()
http = credentials.authorize(http)

service = build('androidpublisher', api_version, http=http, cache_discovery=False)
service = build(serviceName='androidpublisher', version='v3', http=http, cache_discovery=False)

return service
2 changes: 1 addition & 1 deletion mozapkpublisher/common/main_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
def init():
FORMAT = '%(asctime)s - %(filename)s - %(levelname)s - %(message)s'
logging.basicConfig(format=FORMAT, level=logging.DEBUG)
logging.getLogger('oauth2client').setLevel(logging.WARNING)
# logging.getLogger('oauth2client').setLevel(logging.WARNING)
logging.getLogger('androguard').setLevel(logging.WARNING)
17 changes: 14 additions & 3 deletions mozapkpublisher/test/common/test_googleplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def set_up_edit_service_mock(_monkeypatch):
edit_service_mock.insert = lambda body, packageName: new_transaction_mock
general_service_mock.edits = lambda: edit_service_mock

_monkeypatch.setattr('mozapkpublisher.common.googleplay.connect', lambda _, __: general_service_mock)
_monkeypatch.setattr('mozapkpublisher.common.googleplay._connect', lambda _, __: general_service_mock)
return edit_service_mock


Expand Down Expand Up @@ -162,7 +162,12 @@ def test_update_track(monkeypatch):
editId=edit_service._edit_id,
packageName='dummy_package_name',
track='alpha',
body={u'versionCodes': ['2015012345', '2015012347']}
body={
'releases': [{
'status': 'completed',
'versionCodes': ['2015012345', '2015012347'],
}],
},
)

edit_mock.tracks().update.reset_mock()
Expand All @@ -171,7 +176,13 @@ def test_update_track(monkeypatch):
editId=edit_service._edit_id,
packageName='dummy_package_name',
track='rollout',
body={u'userFraction': 0.01, u'versionCodes': ['2015012345', '2015012347']}
body={
'releases': [{
'status': 'completed',
'versionCodes': ['2015012345', '2015012347']},
],
'userFraction': 0.01,
},
)


Expand Down
106 changes: 53 additions & 53 deletions mozapkpublisher/test/test_check_rollout.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# coding: utf-8

import email.utils as eu
import random
import time
from unittest.mock import MagicMock
from unittest.mock import create_autospec

import pytest

from mozapkpublisher import check_rollout
from mozapkpublisher.common import googleplay


def set_up_mocks(_requests_mock, tracks):
Expand All @@ -21,42 +21,38 @@ def set_up_mocks(_requests_mock, tracks):
_requests_mock.head('https://archive.mozilla.org/pub/mobile/releases/{}/SHA512SUMS'.format('62.0'),
status_code=404)

edit_service_mock = MagicMock()
new_transaction_mock = MagicMock()
tracks_mock = MagicMock()
tracks_get_mock = MagicMock()

edit_service_mock.insert = lambda body, packageName: new_transaction_mock
edit_service_mock.tracks = lambda: tracks_mock
new_transaction_mock.execute = lambda: {'id': random.randint(0, 1000)}
tracks_mock.get = lambda editId=None, track=None, packageName=None: tracks_get_mock
tracks_get_mock.execute = tracks

edit_service_mock = create_autospec(googleplay.EditService)
edit_service_mock.get_track_status.return_value = tracks
return edit_service_mock


def test_new_rollout(requests_mock):
"""61.0 is in partial rollout since yesterday, 60.0.1 is at full rollout"""
def tracks():
return {'releases': [
{'name': '61.0',
'versionCodes': ['2015506297', '2015506300', '2015565729', '2015565732'],
'releaseNotes': [
{'language': 'sk', 'text': '* Vylepšenia v rámci Quantum CSS, ktoré urýchľujú načítanie stránok\n* Rýchlejšie posúvanie sa na stránkach'}
],
'status': 'inProgress',
'userFraction': .1,
},
{'name': '60.0.1',
'versionCodes': ['2015558697', '2015558700'],
'status': 'completed',
}]}
tracks = {
"releases": [{
"name": "61.0",
"versionCodes": ["2015506297", "2015506300", "2015565729", "2015565732"],
"releaseNotes": [
{
"language": "sk",
"text": "* Vylepšenia v rámci Quantum CSS, ktoré urýchľujú načítanie stránok\n* Rýchlejšie posúvanie sa na stránkach",
}
],
"status": "inProgress",
"userFraction": 0.1,
}, {
"name": "60.0.1",
"versionCodes": ["2015558697", "2015558700"],
"status": "completed",
}],
}

edit_service_mock = set_up_mocks(requests_mock, tracks)

with pytest.raises(StopIteration):
next(check_rollout.check_rollout(edit_service_mock, 'org.mozilla.firefox', 7))
next(check_rollout.check_rollout(edit_service_mock, 7))

gen = check_rollout.check_rollout(edit_service_mock, 'org.mozilla.firefox', .5)
gen = check_rollout.check_rollout(edit_service_mock, .5)
release, age = next(gen)
assert release['name'] == '61.0'
assert age >= check_rollout.DAY
Expand All @@ -66,20 +62,22 @@ def tracks():

def test_old_rollout(requests_mock):
"""60.0.2 is in partial rollout for a long time; 60.0.1 is at full rollout"""
def tracks():
return {'releases': [
{'name': '60.0.2',
'versionCodes': ['2015562697', '2015562700'],
'status': 'inProgress',
'userFraction': .99,
},
{'name': '60.0.1',
'versionCodes': ['2015558697', '2015558700'],
'status': 'completed',
}]}
tracks = {
"releases": [{
"name": "60.0.2",
"versionCodes": ["2015562697", "2015562700"],
"status": "inProgress",
"userFraction": 0.99,
}, {
"name": "60.0.1",
"versionCodes": ["2015558697", "2015558700"],
"status": "completed",
}],
}

edit_service_mock = set_up_mocks(requests_mock, tracks)

gen = check_rollout.check_rollout(edit_service_mock, 'org.mozilla.firefox', 7)
gen = check_rollout.check_rollout(edit_service_mock, 7)
release, age = next(gen)
assert release['name'] == '60.0.2'
assert age >= 10 * check_rollout.DAY
Expand All @@ -89,18 +87,20 @@ def tracks():

def test_rc_rollout(requests_mock):
"""62.0 is not released yet but RC is being rolled out; 61.0 is at full rollout"""
def tracks():
return {'releases': [
{'name': '62.0',
'versionCodes': ['2015558697', '2015558700'],
'status': 'inProgress',
'userFraction': .05,
},
{'name': '61.0',
'versionCodes': ['2015506297', '2015506300', '2015565729', '2015565732'],
'status': 'completed',
}]}
tracks = {
"releases": [{
"name": "62.0",
"versionCodes": ["2015558697", "2015558700"],
"status": "inProgress",
"userFraction": 0.05,
}, {
"name": "61.0",
"versionCodes": ["2015506297", "2015506300", "2015565729", "2015565732"],
"status": "completed",
}],
}

edit_service_mock = set_up_mocks(requests_mock, tracks)

with pytest.raises(StopIteration):
next(check_rollout.check_rollout(edit_service_mock, 'org.mozilla.firefox', 7))
next(check_rollout.check_rollout(edit_service_mock, 7))
14 changes: 1 addition & 13 deletions mozapkpublisher/test/test_push_apk.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,7 @@

@pytest.fixture
def edit_service_mock():
_edit_service_mock = create_autospec(googleplay.EditService)

def _generate_version_code(apk_file_name):
if apk_file_name == apk_arm.name:
version_code = 0
elif apk_file_name == apk_x86.name:
version_code = 1
else:
raise Exception('Unsupported APK')

return {'versionCode': str(version_code)}

return _edit_service_mock
return create_autospec(googleplay.EditService)


def set_up_mocks(monkeypatch_, edit_service_mock_):
Expand Down

0 comments on commit f15ac8b

Please sign in to comment.