Always create appversions for both Firefox and Firefox for Android (#15644)

We need to keep both in sync because in manifests the distinction
doesn't exist, and validation is currently performed assuming
compatibility for both applications.
This commit is contained in:
Mathieu Pillard 2020-10-06 11:14:50 +02:00 коммит произвёл GitHub
Родитель 2aed8e6c4b
Коммит 28d9862a5f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 106 добавлений и 23 удалений

Просмотреть файл

@ -21,6 +21,11 @@ and maximum versions. The minimum version will use the major number and minor
version from the requested version, and the maximum version will use the major
version and ``*``.
.. note::
Regardless of what application is passed in the URL, this endpoint will
always create versions for both Firefox and Firefox For Android.
Versions that already exist will be skipped.
Examples:

Просмотреть файл

@ -86,11 +86,15 @@ class TestAppVersionsAPI(APIKeyAuthTestMixin, TestCase):
def test_release(self):
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 2
assert AppVersion.objects.count() == 4
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_release_android(self):
self.url = reverse_ns(
@ -98,11 +102,15 @@ class TestAppVersionsAPI(APIKeyAuthTestMixin, TestCase):
kwargs={'application': 'android', 'version': '84.0'})
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 2
assert AppVersion.objects.count() == 4
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='84.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='84.*').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='84.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='84.*').exists()
def test_alpha(self):
self.url = reverse_ns(
@ -110,83 +118,134 @@ class TestAppVersionsAPI(APIKeyAuthTestMixin, TestCase):
kwargs={'application': 'firefox', 'version': '42.0a1'})
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 3
assert AppVersion.objects.count() == 6
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_alpha_already_exists(self):
def test_alpha_already_exists_for_one_app(self):
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.0a1')
self.url = reverse_ns(
'appversions',
kwargs={'application': 'firefox', 'version': '42.0a1'})
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 3
assert AppVersion.objects.count() == 6
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_alpha_release_already_exists(self):
def test_alpha_release_already_exists_for_one_app(self):
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.0')
self.url = reverse_ns(
'appversions',
kwargs={'application': 'firefox', 'version': '42.0a1'})
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 3
assert AppVersion.objects.count() == 6
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_alpha_star_already_exists(self):
def test_alpha_star_already_exists_for_one_app(self):
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.*')
self.url = reverse_ns(
'appversions',
kwargs={'application': 'firefox', 'version': '42.0a1'})
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 3
assert AppVersion.objects.count() == 6
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0a1').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_everything_already_exists(self):
def test_everything_already_exists_for_one_app(self):
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.0')
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.*')
response = self.put(self.url)
assert response.status_code == 202
assert AppVersion.objects.count() == 2
assert response.status_code == 201 # We created some Android stuff.
assert AppVersion.objects.count() == 4
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_alpha_and_star_when_minor_is_not_0(self):
def test_alpha_and_star_when_minor_is_not_0_for_one_app(self):
self.url = reverse_ns(
'appversions',
kwargs={'application': 'firefox', 'version': '42.1a2'})
response = self.put(self.url)
assert response.status_code == 201
assert AppVersion.objects.count() == 3
assert AppVersion.objects.count() == 6
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.1').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.1a2').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.1').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.1a2').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
def test_everything_already_exists(self):
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.0')
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.*')
AppVersion.objects.create(application=amo.ANDROID.id, version='42.0')
AppVersion.objects.create(application=amo.ANDROID.id, version='42.*')
response = self.put(self.url)
assert response.status_code == 202 # Nothing to create at all.
assert AppVersion.objects.count() == 4
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.FIREFOX.id, version='42.*').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.0').exists()
assert AppVersion.objects.filter(
application=amo.ANDROID.id, version='42.*').exists()
class TestCommands(TestCase):

Просмотреть файл

@ -77,12 +77,16 @@ class AppVersionView(APIView):
permission_classes = [GroupPermission(amo.permissions.APPVERSIONS_CREATE)]
def put(self, request, *args, **kwargs):
# For each request, we'll try to create up to 3 versions, one for the
# parameter in the URL, one for the corresponding "release" version if
# it's different (if 79.0a1 is passed, the base would be 79.0. If 79.0
# is passed, then we'd skip that one as they are the same) and a last
# one for the corresponding max version with a star (if 79.0 or 79.0a1
# is passed, then this would be 79.*)
# For each request, we'll try to create up to 3 versions for each app,
# one for the parameter in the URL, one for the corresponding "release"
# version if it's different (if 79.0a1 is passed, the base would be
# 79.0. If 79.0 is passed, then we'd skip that one as they are the
# same) and a last one for the corresponding max version with a star
# (if 79.0 or 79.0a1 is passed, then this would be 79.*)
# We validate the app parameter, but always try to create the versions
# for both Firefox and Firefox for Android anyway, because at the
# extension manifest level there is no difference so for validation
# purposes we want to keep both in sync.
application = amo.APPS.get(kwargs.get('application'))
if not application:
raise ParseError('Invalid application parameter')
@ -93,6 +97,23 @@ class AppVersionView(APIView):
release_version = '%d.%d' % (
version_data['major'], version_data['minor1'] or 0)
star_version = '%d.*' % version_data['major']
created_firefox = self.create_versions_for_app(
application=amo.FIREFOX,
requested_version=requested_version,
release_version=release_version,
star_version=star_version)
created_android = self.create_versions_for_app(
application=amo.ANDROID,
requested_version=requested_version,
release_version=release_version,
star_version=star_version)
created = created_firefox or created_android
status_code = HTTP_201_CREATED if created else HTTP_202_ACCEPTED
return Response(status=status_code)
def create_versions_for_app(
self, *, application, requested_version, release_version,
star_version):
_, created_requested = AppVersion.objects.get_or_create(
application=application.id, version=requested_version)
if requested_version != release_version:
@ -105,6 +126,4 @@ class AppVersionView(APIView):
application=application.id, version=star_version)
else:
created_star = False
created = created_requested or created_release or created_star
status_code = HTTP_201_CREATED if created else HTTP_202_ACCEPTED
return Response(status=status_code)
return created_requested or created_release or created_star