Remove GitHub API and unused files.utils helpers (#10412)

Fixes #10411 

This removes unused files.utils helpers `zip_folder_content` and `repack` along the way.

Once this has been merged, ops can remove `GITHUB_API_USER` and `GITHUB_API_TOKEN` from the environment. I actually wonder where they have been generated, e.g to get them revoked?
This commit is contained in:
Christopher Grebs 2019-01-16 12:01:26 +01:00 коммит произвёл GitHub
Родитель 6e85f809d4
Коммит 300eb84353
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
20 изменённых файлов: 1 добавлений и 732 удалений

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

@ -1,41 +0,0 @@
===============
GitHub Webhooks
===============
.. note::
These APIs are experimental and are currently being worked on. Endpoints
may change without warning. Consider the :ref:`v3 API<api-stable-v3>`
if you need stability.
This API provides an endpoint that works with GitHub to provide add-on validation as a GitHub webhook. This end point is designed to be called specifically from GitHub and will only send API responses back to `api.github.com`.
To set this up on a GitHub repository you will need to:
* Go to `Settings > Webhooks & Services`
* Add a new Webhook with Payload URL of `https://addons.mozilla.org/api/v4/github/validate/`
* Click `Send me everything`
* Click `Update webhook`
At this point the validator will be able to get the data, but won't be able to write a response to GitHub. To enable responses to GitHub:
* Go to `Settings > Collaborators`
* Enter `addons-robot` and select the entry
* Click `Add collaborator`
* You will have to wait for a Mozilla person to respond to the invite
If this service proves useful and this service transitions from its Experimental API state, we will remove as many of these steps as possible.
The validator will run when you create or alter a pull request.
.. http:post:: /api/v4/github/validate/
**Request:**
A `GitHub API webhook <https://developer.github.com/v4/repos/hooks/>`_ body. Currently only `pull_request` events are processed, all others are ignored.
**Response:**
:statuscode 201: request has been processed and a pending message sent back to GitHub.
:statuscode 200: request is not a `pull_request`, it's been accepted.
:statuscode 422: body is invalid.

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

@ -43,4 +43,3 @@ using the API.
ratings
reviewers
signing
github

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

@ -265,6 +265,7 @@ The documentation for `v3` can be accessed at: :ref:`v3-api-index`
v4 API changelog
----------------
* 2019-01-16: Removed /api/{v3,v4,v4dev}/github api entirely. They have been marked as experimental. https://github.com/mozilla/addons-server/issues/10411
* 2019-01-11: added new /reviewers/browse/ endpoint. https://github.com/mozilla/addons-server/issues/10322
* 2018-05-18: renamed /reviews/ endpoint to /ratings/ https://github.com/mozilla/addons-server/issues/6849
* 2018-05-25: renamed ``rating.rating`` property to ``rating.score`` https://github.com/mozilla/addons-server/pull/8332

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

@ -1,39 +0,0 @@
===============
GitHub Webhooks
===============
.. note::
This is an Experimental API and can change at any time.
This API provides an endpoint that works with GitHub to provide add-on validation as a GitHub webhook. This end point is designed to be called specifically from GitHub and will only send API responses back to `api.github.com`.
To set this up on a GitHub repository you will need to:
* Go to `Settings > Webhooks & Services`
* Add a new Webhook with Payload URL of `https://addons.mozilla.org/api/v3/github/validate/`
* Click `Send me everything`
* Click `Update webhook`
At this point the validator will be able to get the data, but won't be able to write a response to GitHub. To enable responses to GitHub:
* Go to `Settings > Collaborators`
* Enter `addons-robot` and select the entry
* Click `Add collaborator`
* You will have to wait for a Mozilla person to respond to the invite
If this service proves useful and this service transitions from its Experimental API state, we will remove as many of these steps as possible.
The validator will run when you create or alter a pull request.
.. http:post:: /api/v3/github/validate/
**Request:**
A `GitHub API webhook <https://developer.github.com/v3/repos/hooks/>`_ body. Currently only `pull_request` events are processed, all others are ignored.
**Response:**
:statuscode 201: request has been processed and a pending message sent back to GitHub.
:statuscode 200: request is not a `pull_request`, it's been accepted.
:statuscode 422: body is invalid.

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

@ -45,4 +45,3 @@ using the API.
reviews
reviewers
signing
github

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

@ -12,7 +12,6 @@ v3_api_urls = [
url(r'^reviewers/', include('olympia.reviewers.api_urls')),
url(r'^', include('olympia.signing.urls')),
url(r'^activity/', include('olympia.activity.urls')),
url(r'^github/', include('olympia.github.urls')),
]
v4_api_urls = [
@ -24,7 +23,6 @@ v4_api_urls = [
url(r'^reviewers/', include('olympia.reviewers.api_urls')),
url(r'^', include('olympia.signing.urls')),
url(r'^activity/', include('olympia.activity.urls')),
url(r'^github/', include('olympia.github.urls')),
]
urlpatterns = [

Двоичные данные
src/olympia/files/fixtures/files/github-repo.xpi

Двоичный файл не отображается.

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

@ -612,48 +612,6 @@ class TestManifestJSONExtractorStaticTheme(TestManifestJSONExtractor):
pass # Irrelevant for static themes.
def test_zip_folder_content():
extension_file = 'src/olympia/files/fixtures/files/extension.xpi'
temp_filename, temp_folder = None, None
try:
temp_folder = utils.extract_zip(extension_file)
assert sorted(os.listdir(temp_folder)) == [
'chrome', 'chrome.manifest', 'install.rdf']
temp_filename = amo.tests.get_temp_filename()
utils.zip_folder_content(temp_folder, temp_filename)
# Make sure the zipped files contain the same files.
with zipfile.ZipFile(temp_filename, mode='r') as new:
with zipfile.ZipFile(extension_file, mode='r') as orig:
assert sorted(new.namelist()) == sorted(orig.namelist())
finally:
if temp_folder is not None and os.path.exists(temp_folder):
amo.utils.rm_local_tmp_dir(temp_folder)
if temp_filename is not None and os.path.exists(temp_filename):
os.unlink(temp_filename)
def test_repack():
# Warning: context managers all the way down. Because they're awesome.
extension_file = 'src/olympia/files/fixtures/files/extension.xpi'
# We don't want to overwrite our fixture, so use a copy.
with amo.tests.copy_file_to_temp(extension_file) as temp_filename:
# This is where we're really testing the repack helper.
with utils.repack(temp_filename) as folder_path:
# Temporary folder contains the unzipped XPI.
assert sorted(os.listdir(folder_path)) == [
'chrome', 'chrome.manifest', 'install.rdf']
# Add a file, which should end up in the repacked file.
with open(os.path.join(folder_path, 'foo.bar'), 'w') as file_:
file_.write('foobar')
# Once we're done with the repack, the temporary folder is removed.
assert not os.path.exists(folder_path)
# And the repacked file has the added file.
assert os.path.exists(temp_filename)
with zipfile.ZipFile(temp_filename, mode='r') as zf:
assert 'foo.bar' in zf.namelist()
assert zf.read('foo.bar') == 'foobar'
@pytest.mark.parametrize('filename, expected_files', [
('webextension_no_id.xpi', [
'README.md', 'beasts', 'button', 'content_scripts', 'manifest.json',

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

@ -29,7 +29,6 @@ from django.utils.translation import ugettext
import flufl.lock
import rdflib
import scandir
import six
from signing_clients.apps import get_signer_organizational_unit_name
@ -1097,41 +1096,6 @@ def get_sha256(file_obj, block_size=io.DEFAULT_BUFFER_SIZE):
return hash_.hexdigest()
def zip_folder_content(folder, filename):
"""Compress the _content_ of a folder."""
with zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED) as dest:
# Add each file/folder from the folder to the zip file.
for root, dirs, files in scandir.walk(folder):
relative_dir = os.path.relpath(root, folder)
for file_ in files:
dest.write(os.path.join(root, file_),
# We want the relative paths for the files.
arcname=os.path.join(relative_dir, file_))
@contextlib.contextmanager
def repack(xpi_path):
"""Unpack the XPI, yield the temp folder, and repack on exit.
Usage:
with repack('foo.xpi') as temp_folder:
# 'foo.xpi' files are extracted to the temp_folder.
modify_files(temp_folder) # Modify the files in the temp_folder.
# The 'foo.xpi' extension is now repacked, with the file changes.
"""
# Unpack.
tempdir = extract_zip(xpi_path, remove=False)
yield tempdir
try:
# Repack.
repacked = u'{0}.repacked'.format(xpi_path) # Temporary file.
zip_folder_content(tempdir, repacked)
# Overwrite the initial file with the repacked one.
shutil.move(repacked, xpi_path)
finally:
rm_local_tmp_dir(tempdir)
def update_version_number(file_obj, new_version_number):
"""Update the manifest to have the new version number."""
# Create a new xpi with the updated version.

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

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

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

@ -1,55 +0,0 @@
import json
import olympia.core.logger
from olympia.amo.celery import task
from olympia.amo.templatetags.jinja_helpers import absolutify
from olympia.amo.urlresolvers import reverse
from olympia.devhub.tasks import validate
from olympia.files.models import FileUpload
from olympia.github.utils import GithubCallback, rezip_file
log = olympia.core.logger.getLogger('z.github')
@task
def process_webhook(upload_pk, callbacks):
log.info('Processing webhook for: {}'.format(upload_pk))
upload = FileUpload.objects.get(pk=upload_pk)
github = GithubCallback(callbacks)
res = github.get()
upload.name = '{}-github-webhook.xpi'.format(upload.pk)
upload.path = rezip_file(res, upload.pk)
upload.save()
log.info('Validating: {}'.format(upload_pk))
validate(
upload,
listed=True,
subtask=process_results.si(upload_pk, callbacks)
)
@task
def process_results(upload_pk, callbacks):
log.info('Processing validation results for: {}'.format(upload_pk))
upload = FileUpload.objects.get(pk=upload_pk)
validation = json.loads(upload.validation) if upload.validation else {}
github = GithubCallback(callbacks)
url = absolutify(
reverse('devhub.upload_detail', args=[upload.uuid]))
if not validation:
log.error('Validation not written: {}'.format(upload_pk))
github.failure()
return
if validation.get('success'):
log.info('Notifying success for: {}'.format(upload_pk))
github.success(url)
return
log.info('Notifying errors for: {}'.format(upload_pk))
github.error(url)

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

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

@ -1,141 +0,0 @@
import zipfile
from copy import deepcopy
from django import forms
from django.test.utils import override_settings
import mock
from olympia.amo.tests import AMOPaths, TestCase
from olympia.github.utils import GithubCallback, GithubRequest, rezip_file
example_root = 'https://api.github.com/repos/org/repo'
example_pull_request = {
'pull_request': {
'head': {
'repo': {
'archive_url': example_root + '/{archive_format}{/ref}',
'statuses_url': example_root + '/statuses/{sha}',
'pulls_url': example_root + '/pulls{/number}'
},
'sha': 'abc'
},
'number': 1,
},
'repository': {
'commits_url': example_root + '/commits{/sha}'
}
}
class TestGithub(TestCase):
def test_github(self):
form = GithubRequest(data=example_pull_request)
assert form.is_valid(), form.errors
assert (
form.cleaned_data['status_url'] ==
'https://api.github.com/repos/org/repo/statuses/abc')
assert (
form.cleaned_data['zip_url'] ==
'https://api.github.com/repos/org/repo/zipball/abc')
def test_invalid(self):
example = deepcopy(example_pull_request)
del example['pull_request']['head']
form = GithubRequest(data=example)
assert not form.is_valid()
def test_url_wrong(self):
example = deepcopy(example_pull_request)
example['pull_request']['head']['repo'] = 'http://a.m.o'
form = GithubRequest(data=example)
assert not form.is_valid()
@override_settings(GITHUB_API_USER='key', GITHUB_API_TOKEN='token')
class GithubBaseTestCase(TestCase):
def setUp(self):
super(GithubBaseTestCase, self).setUp()
patch = mock.patch('olympia.github.utils.requests', autospec=True)
self.addCleanup(patch.stop)
self.requests = patch.start()
self.data = {
'type': 'github',
'status_url': 'https://github/status',
'zip_url': 'https://github/zip',
'sha': 'some:sha'
}
self.github = GithubCallback(self.data)
def check_status(self, status, call=None, url=None, **kw):
url = url or self.data['status_url']
body = {'context': 'mozilla/addons-linter'}
if status != 'comment':
body['state'] = status
body.update(**kw)
if not call:
call = self.requests.post.call_args_list
if len(call) != 1:
# If you don't specify a call to test, we'll get the last
# one off the stack, if there's more than one, that's a
# problem.
raise AssertionError('More than one call to requests.post')
call = call[0]
assert call == mock.call(url, json=body, auth=('key', 'token'))
class TestCallback(GithubBaseTestCase):
def test_create_not_github(self):
with self.assertRaises(ValueError):
GithubCallback({'type': 'bitbucket'})
def test_pending(self):
self.github.pending()
self.check_status('pending')
def test_success(self):
self.github.success('http://a.m.o/')
self.check_status('success', target_url='http://a.m.o/')
def test_error(self):
self.github.error('http://a.m.o/')
self.check_status(
'error', description=mock.ANY, target_url='http://a.m.o/')
def test_failure(self):
self.github.failure()
self.check_status(
'failure', description=mock.ANY)
def test_get(self):
self.github.get()
self.requests.get.assert_called_with(
'https://github/zip'
)
class TestRezip(AMOPaths, TestCase):
def setUp(self):
self.response = mock.Mock()
self.response.content = open(self.xpi_path('github-repo')).read()
def test_rezip(self):
new_path = rezip_file(self.response, 1)
with open(new_path, 'r') as new_file:
new_zip = zipfile.ZipFile(new_file)
self.assertSetEqual(
set([f.filename for f in new_zip.filelist]),
set(['manifest.json', 'index.js'])
)
def test_badzip(self):
with self.settings(FILE_UNZIP_SIZE_LIMIT=5):
with self.assertRaises(forms.ValidationError):
rezip_file(self.response, 1)

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

@ -1,61 +0,0 @@
import json
from django.test.utils import override_settings
import mock
from olympia.amo.templatetags.jinja_helpers import absolutify
from olympia.amo.tests import AMOPaths
from olympia.amo.urlresolvers import reverse
from olympia.files.models import FileUpload
from olympia.github.tasks import process_results, process_webhook
from olympia.github.tests.test_github import GithubBaseTestCase
@override_settings(GITHUB_API_USER='key', GITHUB_API_TOKEN='token')
class TestGithub(AMOPaths, GithubBaseTestCase):
def get_url(self, upload_uuid):
return absolutify(
reverse('devhub.upload_detail', args=[upload_uuid]))
def test_good_results(self):
upload = FileUpload.objects.create(
validation=json.dumps({'success': True, 'errors': 0})
)
process_results(upload.pk, self.data)
self.check_status('success', target_url=self.get_url(upload.uuid))
def test_failed_results(self):
upload = FileUpload.objects.create()
process_results(upload.pk, self.data)
self.check_status('failure', description=mock.ANY)
def test_error_results(self):
upload = FileUpload.objects.create(
validation=json.dumps({
'errors': 1,
'messages': [{
'description': ['foo'],
'file': 'some/file',
'line': 3,
'type': 'error'
}]
})
)
process_results(upload.pk, self.data)
error = self.requests.post.call_args_list[0]
self.check_status(
'error',
call=error, description=mock.ANY,
target_url=self.get_url(upload.uuid))
def test_webhook(self):
upload = FileUpload.objects.create()
self.response = mock.Mock()
self.response.content = open(self.xpi_path('github-repo')).read()
self.requests.get.return_value = self.response
process_webhook(upload.pk, self.data)
self.check_status('success', target_url=self.get_url(upload.uuid))

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

@ -1,82 +0,0 @@
import json
from django.utils.http import urlencode
import mock
import requests
from olympia.amo.tests import AMOPaths, TestCase, reverse_ns
from olympia.files.models import FileUpload
from olympia.github.tests.test_github import (
GithubBaseTestCase, example_pull_request)
class TestGithubView(AMOPaths, GithubBaseTestCase, TestCase):
def setUp(self):
super(TestGithubView, self).setUp()
self.url = reverse_ns('github.validate')
def post(self, data, header=None, data_type=None):
data_type = data_type or 'application/json'
if (data_type == 'application/json'):
data = json.dumps(data)
elif (data_type == 'application/x-www-form-urlencoded'):
data = urlencode({'payload': json.dumps(data)})
return self.client.post(
self.url, data=data,
content_type=data_type,
HTTP_X_GITHUB_EVENT=header or 'pull_request'
)
def complete(self):
pending, success = self.requests.post.call_args_list
self.check_status(
'pending',
call=pending,
url='https://api.github.com/repos/org/repo/statuses/abc'
)
self.check_status(
'success',
call=success,
url='https://api.github.com/repos/org/repo/statuses/abc',
target_url=mock.ANY
)
assert FileUpload.objects.get()
def test_not_pull_request(self):
assert self.post({}, header='meh').status_code == 200
def test_bad_pull_request(self):
assert self.post({'pull_request': {}}).status_code == 422
def setup_xpi(self):
self.response = mock.Mock()
self.response.content = open(self.xpi_path('github-repo')).read()
self.requests.get.return_value = self.response
def test_pending_fails(self):
self.setup_xpi()
post = mock.Mock()
# GitHub returns a 404 when the addons-robot account does not
# have write access.
post.status_code = 404
post.raise_for_status.side_effect = requests.HTTPError(response=post)
self.requests.post.return_value = post
res = self.post(example_pull_request)
assert 'write access' in json.loads(res.content)['details']
def test_good_not_json(self):
self.setup_xpi()
assert self.post(
example_pull_request,
data_type='application/x-www-form-urlencoded').status_code == 201
self.complete()
def test_good(self):
self.setup_xpi()
assert self.post(example_pull_request).status_code == 201
self.complete()

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

@ -1,8 +0,0 @@
from django.conf.urls import url
from olympia.github.views import GithubView
urlpatterns = [
url(r'^validate/$', GithubView.as_view(), name='github.validate'),
]

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

@ -1,153 +0,0 @@
import os
import uuid
import zipfile
from django import forms
from django.conf import settings
from django.core.files.storage import default_storage as storage
import requests
from django_statsd.clients import statsd
import olympia.core.logger
from olympia.amo.templatetags.jinja_helpers import user_media_path
from olympia.files.utils import SafeZip
log = olympia.core.logger.getLogger('z.github')
class GithubCallback(object):
def __init__(self, data):
if data['type'] != 'github':
raise ValueError('Not a github callback.')
self.data = data
def get(self):
log.info('Getting zip from github: {}'.format(self.data['zip_url']))
with statsd.timer('github.zip'):
res = requests.get(self.data['zip_url'])
res.raise_for_status()
return res
def post(self, url, data):
msg = data.get('state', 'comment')
log.info('Setting github to: {} at: {}'.format(msg, url))
with statsd.timer('github.{}'.format(msg)):
data['context'] = 'mozilla/addons-linter'
log.info('Body: {}'.format(data))
res = requests.post(
url,
json=data,
auth=(settings.GITHUB_API_USER, settings.GITHUB_API_TOKEN))
log.info('Response: {}'.format(res.content))
res.raise_for_status()
def pending(self):
self.post(self.data['status_url'], data={'state': 'pending'})
def success(self, url):
self.post(self.data['status_url'], data={
'state': 'success',
'target_url': url
})
def error(self, url):
self.post(self.data['status_url'], data={
'state': 'error',
# Not localising because we aren't sure what locale to localise to.
# I would like to pass a longer string here that shows more details
# however, we are limited to "A short description of the status."
# Which means all the fancy things I wanted to do got truncated.
'description': 'This add-on did not validate.',
'target_url': url
})
def failure(self):
data = {
'state': 'failure',
# Not localising because we aren't sure what locale to localise to.
'description': 'The validator failed to run correctly.'
}
self.post(self.data['status_url'], data=data)
class GithubRequest(forms.Form):
status_url = forms.URLField(required=False)
zip_url = forms.URLField(required=False)
sha = forms.CharField(required=False)
@property
def repo(self):
return self.data['pull_request']['head']['repo']
@property
def sha(self):
return self.data['pull_request']['head']['sha']
def get_status(self):
return self.repo['statuses_url'].replace('{sha}', self.sha)
def get_zip(self):
return (
self.repo['archive_url']
.replace('{archive_format}', 'zipball')
.replace('{/ref}', '/' + self.sha))
def validate_url(self, url):
if not url.startswith('https://api.github.com/'):
raise forms.ValidationError('Invalid URL: {}'.format(url))
return url
def clean(self):
fields = (
('status_url', self.get_status),
('zip_url', self.get_zip),
)
for url, method in fields:
try:
self.cleaned_data[url] = self.validate_url(method())
except Exception:
log.error('Invalid data in processing JSON')
raise forms.ValidationError('Invalid data')
self.cleaned_data['sha'] = self.data['pull_request']['head']['sha']
self.cleaned_data['type'] = 'github'
return self.cleaned_data
def rezip_file(response, pk):
# An .xpi does not have a directory inside the zip, yet zips from github
# do, so we'll need to rezip the file before passing it through to the
# validator.
loc = os.path.join(user_media_path('addons'), 'temp', uuid.uuid4().hex)
old_filename = '{}_github_webhook.zip'.format(pk)
old_path = os.path.join(loc, old_filename)
with storage.open(old_path, 'wb') as old:
old.write(response.content)
new_filename = '{}_github_webhook.xpi'.format(pk)
new_path = os.path.join(loc, new_filename)
old_zip = SafeZip(old_path)
if not old_zip.is_valid:
raise
with storage.open(new_path, 'w') as new:
new_zip = zipfile.ZipFile(new, 'w')
for obj in old_zip.filelist:
# Basically strip off the leading directory.
new_filename = obj.filename.partition('/')[-1]
if not new_filename:
continue
new_zip.writestr(new_filename, old_zip.read(obj.filename))
new_zip.close()
old_zip.close()
return new_path

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

@ -1,61 +0,0 @@
import json
import requests
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
import olympia.core.logger
from olympia.files.models import FileUpload
from olympia.github.tasks import process_webhook
from olympia.github.utils import GithubCallback, GithubRequest
log = olympia.core.logger.getLogger('z.github')
class GithubView(APIView):
def post(self, request):
if request.META.get('HTTP_X_GITHUB_EVENT') != 'pull_request':
# That's ok, we are just going to ignore it, we'll return a 2xx
# response so github doesn't report it as an error.
return Response({}, status=status.HTTP_200_OK)
# If the content-type is form-urlencoded the JSON is sent in the
# payload parameter.
#
# See: https://developer.github.com/webhooks/creating/#content-type
if (request.META.get('CONTENT_TYPE') ==
'application/x-www-form-urlencoded'):
data = json.loads(request.data['payload'])
else:
data = request.data
github = GithubRequest(data=data)
if not github.is_valid():
return Response({}, status=422)
data = github.cleaned_data
upload = FileUpload.objects.create()
log.info('Created FileUpload from github api: {}'.format(upload.pk))
try:
github = GithubCallback(data)
github.pending()
except requests.HTTPError as err:
# This is a common error, where the user hasn't set up add-ons
# robot as a contributor, so we'll get a 404 from GitHub. Let's
# try and get a nice error message back into the GitHub UI.
if err.response.status_code == status.HTTP_404_NOT_FOUND:
return Response({
'details': (
'Writing pending status failed. Please ensure '
'the addons.mozilla.org GitHub account has write '
'access to this repository.')},
status=status.HTTP_404_NOT_FOUND)
process_webhook.delay(upload.pk, data)
return Response({}, status=status.HTTP_201_CREATED)

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

@ -475,7 +475,6 @@ INSTALLED_APPS = (
'olympia.devhub',
'olympia.discovery',
'olympia.files',
'olympia.github',
'olympia.legacy_api',
'olympia.legacy_discovery',
'olympia.lib.es',
@ -1227,10 +1226,6 @@ CELERY_TASK_ROUTES = {
'olympia.zadmin.tasks.admin_email': {'queue': 'zadmin'},
'olympia.zadmin.tasks.celery_error': {'queue': 'zadmin'},
# Github API
'olympia.github.tasks.process_results': {'queue': 'devhub'},
'olympia.github.tasks.process_webhook': {'queue': 'devhub'},
# Temporary tasks to crush existing images.
# Go in the addons queue to leave the 'devhub' queue free to process
# validations etc.
@ -1853,10 +1848,6 @@ FXA_SQS_AWS_WAIT_TIME = 20 # Seconds.
AWS_STATS_S3_BUCKET = env('AWS_STATS_S3_BUCKET', default=None)
AWS_STATS_S3_PREFIX = env('AWS_STATS_S3_PREFIX', default='amo_stats')
# For the Github webhook API.
GITHUB_API_USER = env('GITHUB_API_USER', default='')
GITHUB_API_TOKEN = env('GITHUB_API_TOKEN', default='')
MIGRATED_LWT_DEFAULT_OWNER_EMAIL = 'addons-team+landfill-account@mozilla.com'
MIGRATED_LWT_UPDATES_ENABLED = False