Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

deployment bits

  • Loading branch information...
commit 673fc55a7a5de1a47883705d8dc586790fd5fdc8 1 parent 2af8fe8
Allen Short washort authored
2  gelato/admin/admin.py
@@ -116,8 +116,8 @@ class ApplicationAdmin(admin.ModelAdmin):
116 116 def register():
117 117 # admin.site.register(models.BlacklistedGuid)
118 118 # admin.site.register(models.Feature, FeatureAdmin)
  119 + admin.site.register(addons.Category, CategoryAdmin)
119 120 admin.site.register(addons.AddonBase, AddonAdmin)
120   - # admin.site.register(models.Category, CategoryAdmin)
121 121 # admin.site.register(models.FrozenAddon, FrozenAddonAdmin)
122 122 # admin.site.register(models.CompatOverride, CompatOverrideAdmin)
123 123
142 gelato/admin/settings.py
@@ -69,7 +69,7 @@
69 69 DATABASES = {
70 70 'default': {
71 71 'NAME': 'zamboni',
72   - 'ENGINE': 'django.db.backends.mysql',
  72 + 'ENGINE': 'mysql_pymysql',
73 73 'HOST': '',
74 74 'PORT': '',
75 75 'USER': '',
@@ -303,7 +303,7 @@ def JINJA_CONFIG():
303 303 # Auth
304 304 AUTHENTICATION_BACKENDS = (
305 305 'django_browserid.auth.BrowserIDBackend',
306   - 'users.backends.AmoUserBackend',
  306 + 'gelato.models.users.AmoUserBackend',
307 307 'cake.backends.SessionBackend',
308 308 )
309 309 AUTH_PROFILE_MODULE = 'users.UserProfile'
@@ -319,12 +319,12 @@ def JINJA_CONFIG():
319 319 'versions',
320 320 'users',
321 321 # Third party apps
322   - 'djcelery',
  322 + #'djcelery',
323 323 'django_extensions',
324 324 'django_nose',
325 325 'raven.contrib.django',
326   - 'gunicorn',
327   - 'piston',
  326 + #'gunicorn',
  327 + #'piston',
328 328 'waffle',
329 329
330 330 # Django contrib apps
@@ -336,9 +336,9 @@ def JINJA_CONFIG():
336 336 'django.contrib.sessions',
337 337
338 338 # Has to load after auth
339   - 'django_browserid',
340   - 'django_statsd',
341   - 'radagast',
  339 + #'django_browserid',
  340 + #'django_statsd',
  341 + #'radagast',
342 342 )
343 343
344 344 # These apps will be removed from INSTALLED_APPS in a production environment.
@@ -890,7 +890,7 @@ def JINJA_CONFIG():
890 890 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
891 891 SESSION_EXPIRE_AT_BROWSER_CLOSE = True
892 892 SESSION_COOKIE_AGE = 1209600
893   -SESSION_COOKIE_SECURE = False
  893 +SESSION_COOKIE_SECURE = True
894 894 SESSION_COOKIE_HTTPONLY = True
895 895 SESSION_COOKIE_DOMAIN = ".%s" % DOMAIN # bug 608797
896 896 MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
@@ -953,68 +953,68 @@ def JINJA_CONFIG():
953 953 'AddonReviews#Step_2:_Automatic_validation')
954 954
955 955
956   -## Celery
957   -BROKER_HOST = 'localhost'
958   -BROKER_PORT = 5672
959   -BROKER_USER = 'zamboni'
960   -BROKER_PASSWORD = 'zamboni'
961   -BROKER_VHOST = 'zamboni'
962   -BROKER_CONNECTION_TIMEOUT = 0.1
963   -CELERY_RESULT_BACKEND = 'amqp'
964   -CELERY_IGNORE_RESULT = True
965   -CELERY_SEND_TASK_ERROR_EMAILS = True
966   -CELERYD_LOG_LEVEL = logging.INFO
967   -CELERYD_HIJACK_ROOT_LOGGER = False
968   -CELERY_IMPORTS = ('lib.video.tasks', 'lib.metrics')
969   -# We have separate celeryds for processing devhub & images as fast as possible
970   -# Some notes:
971   -# - always add routes here instead of @task(queue=<name>)
972   -# - when adding a queue, be sure to update deploy.py so that it gets restarted
973   -CELERY_ROUTES = {
974   - # Devhub.
975   - 'devhub.tasks.validator': {'queue': 'devhub'},
976   - 'devhub.tasks.compatibility_check': {'queue': 'devhub'},
977   - 'devhub.tasks.fetch_manifest': {'queue': 'devhub'},
978   - 'devhub.tasks.fetch_icon': {'queue': 'devhub'},
979   - 'devhub.tasks.file_validator': {'queue': 'devhub'},
980   - 'devhub.tasks.packager': {'queue': 'devhub'},
981   -
982   - # Videos.
983   - 'lib.video.tasks.resize_video': {'queue': 'devhub'},
984   -
985   - # Images.
986   - 'bandwagon.tasks.resize_icon': {'queue': 'images'},
987   - 'users.tasks.resize_photo': {'queue': 'images'},
988   - 'users.tasks.delete_photo': {'queue': 'images'},
989   - 'devhub.tasks.resize_icon': {'queue': 'images'},
990   - 'devhub.tasks.resize_preview': {'queue': 'images'},
991   -
992   - # Bulk.
993   - 'zadmin.tasks.bulk_validate_file': {'queue': 'bulk'},
994   - 'zadmin.tasks.tally_validation_results': {'queue': 'bulk'},
995   - 'zadmin.tasks.add_validation_jobs': {'queue': 'bulk'},
996   - 'zadmin.tasks.notify_success': {'queue': 'bulk'},
997   - 'zadmin.tasks.notify_failed': {'queue': 'bulk'},
998   - 'devhub.tasks.flag_binary': {'queue': 'bulk'},
999   - 'stats.tasks.index_update_counts': {'queue': 'bulk'},
1000   - 'stats.tasks.index_download_counts': {'queue': 'bulk'},
1001   -}
1002   -
1003   -# This is just a place to store these values, you apply them in your
1004   -# task decorator, for example:
1005   -# @task(time_limit=CELERY_TIME_LIMITS['lib...']['hard'])
1006   -# Otherwise your task will use the default settings.
1007   -CELERY_TIME_LIMITS = {
1008   - 'lib.video.tasks.resize_video': {'soft': 360, 'hard': 600},
1009   -}
1010   -
1011   -# When testing, we always want tasks to raise exceptions. Good for sanity.
1012   -CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
1013   -
1014   -# Time in seconds before celery.exceptions.SoftTimeLimitExceeded is raised.
1015   -# The task can catch that and recover but should exit ASAP. Note that there is
1016   -# a separate, shorter timeout for validation tasks.
1017   -CELERYD_TASK_SOFT_TIME_LIMIT = 60 * 2
  956 +# ## Celery
  957 +# BROKER_HOST = 'localhost'
  958 +# BROKER_PORT = 5672
  959 +# BROKER_USER = 'zamboni'
  960 +# BROKER_PASSWORD = 'zamboni'
  961 +# BROKER_VHOST = 'zamboni'
  962 +# BROKER_CONNECTION_TIMEOUT = 0.1
  963 +# CELERY_RESULT_BACKEND = 'amqp'
  964 +# CELERY_IGNORE_RESULT = True
  965 +# CELERY_SEND_TASK_ERROR_EMAILS = True
  966 +# CELERYD_LOG_LEVEL = logging.INFO
  967 +# CELERYD_HIJACK_ROOT_LOGGER = False
  968 +# CELERY_IMPORTS = ('lib.video.tasks', 'lib.metrics')
  969 +# # We have separate celeryds for processing devhub & images as fast as possible
  970 +# # Some notes:
  971 +# # - always add routes here instead of @task(queue=<name>)
  972 +# # - when adding a queue, be sure to update deploy.py so that it gets restarted
  973 +# CELERY_ROUTES = {
  974 +# # Devhub.
  975 +# 'devhub.tasks.validator': {'queue': 'devhub'},
  976 +# 'devhub.tasks.compatibility_check': {'queue': 'devhub'},
  977 +# 'devhub.tasks.fetch_manifest': {'queue': 'devhub'},
  978 +# 'devhub.tasks.fetch_icon': {'queue': 'devhub'},
  979 +# 'devhub.tasks.file_validator': {'queue': 'devhub'},
  980 +# 'devhub.tasks.packager': {'queue': 'devhub'},
  981 +
  982 +# # Videos.
  983 +# 'lib.video.tasks.resize_video': {'queue': 'devhub'},
  984 +
  985 +# # Images.
  986 +# 'bandwagon.tasks.resize_icon': {'queue': 'images'},
  987 +# 'users.tasks.resize_photo': {'queue': 'images'},
  988 +# 'users.tasks.delete_photo': {'queue': 'images'},
  989 +# 'devhub.tasks.resize_icon': {'queue': 'images'},
  990 +# 'devhub.tasks.resize_preview': {'queue': 'images'},
  991 +
  992 +# # Bulk.
  993 +# 'zadmin.tasks.bulk_validate_file': {'queue': 'bulk'},
  994 +# 'zadmin.tasks.tally_validation_results': {'queue': 'bulk'},
  995 +# 'zadmin.tasks.add_validation_jobs': {'queue': 'bulk'},
  996 +# 'zadmin.tasks.notify_success': {'queue': 'bulk'},
  997 +# 'zadmin.tasks.notify_failed': {'queue': 'bulk'},
  998 +# 'devhub.tasks.flag_binary': {'queue': 'bulk'},
  999 +# 'stats.tasks.index_update_counts': {'queue': 'bulk'},
  1000 +# 'stats.tasks.index_download_counts': {'queue': 'bulk'},
  1001 +# }
  1002 +
  1003 +# # This is just a place to store these values, you apply them in your
  1004 +# # task decorator, for example:
  1005 +# # @task(time_limit=CELERY_TIME_LIMITS['lib...']['hard'])
  1006 +# # Otherwise your task will use the default settings.
  1007 +# CELERY_TIME_LIMITS = {
  1008 +# 'lib.video.tasks.resize_video': {'soft': 360, 'hard': 600},
  1009 +# }
  1010 +
  1011 +# # When testing, we always want tasks to raise exceptions. Good for sanity.
  1012 +# CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
  1013 +
  1014 +# # Time in seconds before celery.exceptions.SoftTimeLimitExceeded is raised.
  1015 +# # The task can catch that and recover but should exit ASAP. Note that there is
  1016 +# # a separate, shorter timeout for validation tasks.
  1017 +# CELERYD_TASK_SOFT_TIME_LIMIT = 60 * 2
1018 1018
1019 1019 ## Fixture Magic
1020 1020 CUSTOM_DUMPS = {
101 scripts/update/update.py
... ... @@ -0,0 +1,101 @@
  1 +"""
  2 +Deploy this project in dev/stage/production.
  3 +
  4 +Requires commander_ which is installed on the systems that need it.
  5 +
  6 +.. _commander: https://github.com/oremj/commander
  7 +"""
  8 +
  9 +import os
  10 +import sys
  11 +
  12 +sys.path.append(os.path.dirname(os.path.abspath(__file__)))
  13 +
  14 +from commander.deploy import task, hostgroups, BadReturnCode
  15 +import commander_settings as settings
  16 +
  17 +@task
  18 +def create_virtualenv(ctx):
  19 + venv = settings.VIRTUAL_ENV
  20 + try:
  21 + try:
  22 + ctx.local("virtualenv --distribute --never-download %s" % venv)
  23 + except BadReturnCode:
  24 + pass # if this is really broken, then the pip install should fail
  25 +
  26 + ctx.local("%s/bin/pip install --exists-action=w --no-deps --no-index "
  27 + "--download-cache=/tmp/pip-cache -f %s "
  28 + "-r %s/requirements.txt" %
  29 + (venv, settings.PYREPO, settings.SRC_DIR))
  30 + finally:
  31 + # make sure this always runs
  32 + ctx.local("rm -f %s/lib/python2.6/no-global-site-packages.txt" % venv)
  33 + ctx.local("%s/bin/python /usr/bin/virtualenv --relocatable %s"
  34 + % (venv, venv))
  35 +
  36 +
  37 +@task
  38 +def update_code(ctx, tag):
  39 + """Update the code to a specific git reference (tag/sha/etc)."""
  40 + with ctx.lcd(settings.SRC_DIR):
  41 + ctx.local('git fetch')
  42 + ctx.local('git reset --hard %s' % tag)
  43 +
  44 +@task
  45 +def update_assets(ctx):
  46 + with ctx.lcd(settings.SRC_DIR):
  47 + ctx.local("%s manage.py collectstatic --noinput" % settings.PYTHON)
  48 +
  49 +
  50 +@task
  51 +def checkin_changes(ctx):
  52 + """Use the local, IT-written deploy script to check in changes."""
  53 + ctx.local(settings.DEPLOY_SCRIPT)
  54 +
  55 +
  56 +@hostgroups(settings.WEB_HOSTGROUP, remote_kwargs={'ssh_key': settings.SSH_KEY})
  57 +def deploy_app(ctx):
  58 + """Call the remote update script to push changes to webheads."""
  59 + ctx.remote(settings.REMOTE_UPDATE_SCRIPT)
  60 + ctx.remote('service %s reload' % settings.GUNICORN)
  61 +
  62 +
  63 +@task
  64 +def update_info(ctx):
  65 + """Write info about the current state to a publicly visible file."""
  66 + with ctx.lcd(settings.SRC_DIR):
  67 + ctx.local('date')
  68 + ctx.local('git branch')
  69 + ctx.local('git log -3')
  70 + ctx.local('git status')
  71 +
  72 +@task
  73 +def pre_update(ctx, ref=settings.UPDATE_REF):
  74 + """Update code to pick up changes to this file."""
  75 + update_code(ref)
  76 + update_info()
  77 +
  78 +
  79 +@task
  80 +def post_update(ctx):
  81 + pass
  82 +
  83 +@task
  84 +def update(ctx):
  85 +# update_assets()
  86 + pass
  87 +
  88 +
  89 +@task
  90 +def deploy(ctx):
  91 + checkin_changes()
  92 + deploy_app()
  93 +
  94 +
  95 +@task
  96 +def update_site(ctx, tag):
  97 + """Update the app to prep for deployment."""
  98 + pre_update(tag)
  99 + create_virtualenv()
  100 + update()
  101 + post_update()
0  sites/__init__.py
No changes.
0  sites/altdev/__init__.py
No changes.
140 gelato/admin/#settings.py# → sites/altdev/settings.py
@@ -69,7 +69,7 @@
69 69 DATABASES = {
70 70 'default': {
71 71 'NAME': 'zamboni',
72   - 'ENGINE': 'django.db.backends.mysql',
  72 + 'ENGINE': 'mysql_pymysql',
73 73 'HOST': '',
74 74 'PORT': '',
75 75 'USER': '',
@@ -303,7 +303,7 @@ def JINJA_CONFIG():
303 303 # Auth
304 304 AUTHENTICATION_BACKENDS = (
305 305 'django_browserid.auth.BrowserIDBackend',
306   - 'users.backends.AmoUserBackend',
  306 + 'gelato.models.users.AmoUserBackend',
307 307 'cake.backends.SessionBackend',
308 308 )
309 309 AUTH_PROFILE_MODULE = 'users.UserProfile'
@@ -319,12 +319,12 @@ def JINJA_CONFIG():
319 319 'versions',
320 320 'users',
321 321 # Third party apps
322   - 'djcelery',
  322 + #'djcelery',
323 323 'django_extensions',
324 324 'django_nose',
325 325 'raven.contrib.django',
326   - 'gunicorn',
327   - 'piston',
  326 + #'gunicorn',
  327 + #'piston',
328 328 'waffle',
329 329
330 330 # Django contrib apps
@@ -336,9 +336,9 @@ def JINJA_CONFIG():
336 336 'django.contrib.sessions',
337 337
338 338 # Has to load after auth
339   - 'django_browserid',
340   - 'django_statsd',
341   - 'radagast',
  339 + #'django_browserid',
  340 + #'django_statsd',
  341 + #'radagast',
342 342 )
343 343
344 344 # These apps will be removed from INSTALLED_APPS in a production environment.
@@ -953,68 +953,68 @@ def JINJA_CONFIG():
953 953 'AddonReviews#Step_2:_Automatic_validation')
954 954
955 955
956   -## Celery
957   -BROKER_HOST = 'localhost'
958   -BROKER_PORT = 5672
959   -BROKER_USER = 'zamboni'
960   -BROKER_PASSWORD = 'zamboni'
961   -BROKER_VHOST = 'zamboni'
962   -BROKER_CONNECTION_TIMEOUT = 0.1
963   -CELERY_RESULT_BACKEND = 'amqp'
964   -CELERY_IGNORE_RESULT = True
965   -CELERY_SEND_TASK_ERROR_EMAILS = True
966   -CELERYD_LOG_LEVEL = logging.INFO
967   -CELERYD_HIJACK_ROOT_LOGGER = False
968   -CELERY_IMPORTS = ('lib.video.tasks', 'lib.metrics')
969   -# We have separate celeryds for processing devhub & images as fast as possible
970   -# Some notes:
971   -# - always add routes here instead of @task(queue=<name>)
972   -# - when adding a queue, be sure to update deploy.py so that it gets restarted
973   -CELERY_ROUTES = {
974   - # Devhub.
975   - 'devhub.tasks.validator': {'queue': 'devhub'},
976   - 'devhub.tasks.compatibility_check': {'queue': 'devhub'},
977   - 'devhub.tasks.fetch_manifest': {'queue': 'devhub'},
978   - 'devhub.tasks.fetch_icon': {'queue': 'devhub'},
979   - 'devhub.tasks.file_validator': {'queue': 'devhub'},
980   - 'devhub.tasks.packager': {'queue': 'devhub'},
981   -
982   - # Videos.
983   - 'lib.video.tasks.resize_video': {'queue': 'devhub'},
984   -
985   - # Images.
986   - 'bandwagon.tasks.resize_icon': {'queue': 'images'},
987   - 'users.tasks.resize_photo': {'queue': 'images'},
988   - 'users.tasks.delete_photo': {'queue': 'images'},
989   - 'devhub.tasks.resize_icon': {'queue': 'images'},
990   - 'devhub.tasks.resize_preview': {'queue': 'images'},
991   -
992   - # Bulk.
993   - 'zadmin.tasks.bulk_validate_file': {'queue': 'bulk'},
994   - 'zadmin.tasks.tally_validation_results': {'queue': 'bulk'},
995   - 'zadmin.tasks.add_validation_jobs': {'queue': 'bulk'},
996   - 'zadmin.tasks.notify_success': {'queue': 'bulk'},
997   - 'zadmin.tasks.notify_failed': {'queue': 'bulk'},
998   - 'devhub.tasks.flag_binary': {'queue': 'bulk'},
999   - 'stats.tasks.index_update_counts': {'queue': 'bulk'},
1000   - 'stats.tasks.index_download_counts': {'queue': 'bulk'},
1001   -}
1002   -
1003   -# This is just a place to store these values, you apply them in your
1004   -# task decorator, for example:
1005   -# @task(time_limit=CELERY_TIME_LIMITS['lib...']['hard'])
1006   -# Otherwise your task will use the default settings.
1007   -CELERY_TIME_LIMITS = {
1008   - 'lib.video.tasks.resize_video': {'soft': 360, 'hard': 600},
1009   -}
1010   -
1011   -# When testing, we always want tasks to raise exceptions. Good for sanity.
1012   -CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
1013   -
1014   -# Time in seconds before celery.exceptions.SoftTimeLimitExceeded is raised.
1015   -# The task can catch that and recover but should exit ASAP. Note that there is
1016   -# a separate, shorter timeout for validation tasks.
1017   -CELERYD_TASK_SOFT_TIME_LIMIT = 60 * 2
  956 +# ## Celery
  957 +# BROKER_HOST = 'localhost'
  958 +# BROKER_PORT = 5672
  959 +# BROKER_USER = 'zamboni'
  960 +# BROKER_PASSWORD = 'zamboni'
  961 +# BROKER_VHOST = 'zamboni'
  962 +# BROKER_CONNECTION_TIMEOUT = 0.1
  963 +# CELERY_RESULT_BACKEND = 'amqp'
  964 +# CELERY_IGNORE_RESULT = True
  965 +# CELERY_SEND_TASK_ERROR_EMAILS = True
  966 +# CELERYD_LOG_LEVEL = logging.INFO
  967 +# CELERYD_HIJACK_ROOT_LOGGER = False
  968 +# CELERY_IMPORTS = ('lib.video.tasks', 'lib.metrics')
  969 +# # We have separate celeryds for processing devhub & images as fast as possible
  970 +# # Some notes:
  971 +# # - always add routes here instead of @task(queue=<name>)
  972 +# # - when adding a queue, be sure to update deploy.py so that it gets restarted
  973 +# CELERY_ROUTES = {
  974 +# # Devhub.
  975 +# 'devhub.tasks.validator': {'queue': 'devhub'},
  976 +# 'devhub.tasks.compatibility_check': {'queue': 'devhub'},
  977 +# 'devhub.tasks.fetch_manifest': {'queue': 'devhub'},
  978 +# 'devhub.tasks.fetch_icon': {'queue': 'devhub'},
  979 +# 'devhub.tasks.file_validator': {'queue': 'devhub'},
  980 +# 'devhub.tasks.packager': {'queue': 'devhub'},
  981 +
  982 +# # Videos.
  983 +# 'lib.video.tasks.resize_video': {'queue': 'devhub'},
  984 +
  985 +# # Images.
  986 +# 'bandwagon.tasks.resize_icon': {'queue': 'images'},
  987 +# 'users.tasks.resize_photo': {'queue': 'images'},
  988 +# 'users.tasks.delete_photo': {'queue': 'images'},
  989 +# 'devhub.tasks.resize_icon': {'queue': 'images'},
  990 +# 'devhub.tasks.resize_preview': {'queue': 'images'},
  991 +
  992 +# # Bulk.
  993 +# 'zadmin.tasks.bulk_validate_file': {'queue': 'bulk'},
  994 +# 'zadmin.tasks.tally_validation_results': {'queue': 'bulk'},
  995 +# 'zadmin.tasks.add_validation_jobs': {'queue': 'bulk'},
  996 +# 'zadmin.tasks.notify_success': {'queue': 'bulk'},
  997 +# 'zadmin.tasks.notify_failed': {'queue': 'bulk'},
  998 +# 'devhub.tasks.flag_binary': {'queue': 'bulk'},
  999 +# 'stats.tasks.index_update_counts': {'queue': 'bulk'},
  1000 +# 'stats.tasks.index_download_counts': {'queue': 'bulk'},
  1001 +# }
  1002 +
  1003 +# # This is just a place to store these values, you apply them in your
  1004 +# # task decorator, for example:
  1005 +# # @task(time_limit=CELERY_TIME_LIMITS['lib...']['hard'])
  1006 +# # Otherwise your task will use the default settings.
  1007 +# CELERY_TIME_LIMITS = {
  1008 +# 'lib.video.tasks.resize_video': {'soft': 360, 'hard': 600},
  1009 +# }
  1010 +
  1011 +# # When testing, we always want tasks to raise exceptions. Good for sanity.
  1012 +# CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
  1013 +
  1014 +# # Time in seconds before celery.exceptions.SoftTimeLimitExceeded is raised.
  1015 +# # The task can catch that and recover but should exit ASAP. Note that there is
  1016 +# # a separate, shorter timeout for validation tasks.
  1017 +# CELERYD_TASK_SOFT_TIME_LIMIT = 60 * 2
1018 1018
1019 1019 ## Fixture Magic
1020 1020 CUSTOM_DUMPS = {
0  sites/dev/__init__.py
No changes.
1,447 sites/dev/settings.py
... ... @@ -0,0 +1,1447 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Django settings for zamboni project.
  3 +
  4 +import os
  5 +import logging
  6 +import socket
  7 +
  8 +from django.utils.functional import lazy
  9 +from metlog.config import client_from_dict_config
  10 +
  11 +WAFFLE_TABLE_SUFFIX = 'amo'
  12 +LOG_TABLE_SUFFIX = ''
  13 +EVENT_TABLE_SUFFIX = ''
  14 +
  15 +# jingo-minify settings
  16 +CACHEBUST_IMGS = True
  17 +try:
  18 + # If we have build ids available, we'll grab them here and add them to our
  19 + # CACHE_PREFIX. This will let us not have to flush memcache during updates
  20 + # and it will let us preload data into it before a production push.
  21 + from build import BUILD_ID_CSS, BUILD_ID_JS
  22 + build_id = "%s%s" % (BUILD_ID_CSS[:2], BUILD_ID_JS[:2])
  23 +except ImportError:
  24 + build_id = ""
  25 +
  26 +# jingo-minify: Style sheet media attribute default
  27 +CSS_MEDIA_DEFAULT = 'all'
  28 +
  29 +# Make filepaths relative to the root of zamboni.
  30 +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  31 +path = lambda *a: os.path.join(ROOT, *a)
  32 +
  33 +# We need to track this because hudson can't just call its checkout "zamboni".
  34 +# It puts it in a dir called "workspace". Way to be, hudson.
  35 +ROOT_PACKAGE = os.path.basename(ROOT)
  36 +
  37 +DEBUG = True
  38 +TEMPLATE_DEBUG = DEBUG
  39 +DEBUG_PROPAGATE_EXCEPTIONS = True
  40 +
  41 +# need to view JS errors on a remote device? (requires node)
  42 +# > npm install now
  43 +# > node media/js/debug/remote_debug_server.node.js
  44 +# REMOTE_JS_DEBUG = 'localhost:37767'
  45 +# then connect to http://localhost:8080/ to view
  46 +REMOTE_JS_DEBUG = False
  47 +
  48 +# LESS CSS OPTIONS (Debug only)
  49 +LESS_PREPROCESS = False # Compile LESS with Node, rather than client-side JS?
  50 +LESS_LIVE_REFRESH = False # Refresh the CSS on save?
  51 +LESS_BIN = 'lessc'
  52 +
  53 +# Path to uglifyjs. When not None, this will be used to minify JavaScript
  54 +# instead of YUI.
  55 +UGLIFY_BIN = None
  56 +
  57 +ADMINS = (
  58 + # ('Your Name', 'your_email@domain.com'),
  59 +)
  60 +MANAGERS = ADMINS
  61 +
  62 +FLIGTAR = 'amo-admins@mozilla.org'
  63 +EDITORS_EMAIL = 'amo-editors@mozilla.org'
  64 +SENIOR_EDITORS_EMAIL = 'amo-admin-reviews@mozilla.org'
  65 +MARKETPLACE_EMAIL = 'amo-marketplace@mozilla.org'
  66 +ABUSE_EMAIL = 'marketplace-abuse@mozilla.org'
  67 +NOBODY_EMAIL = 'nobody@mozilla.org'
  68 +
  69 +DATABASES = {
  70 + 'default': {
  71 + 'NAME': 'zamboni',
  72 + 'ENGINE': 'mysql_pymysql',
  73 + 'HOST': '',
  74 + 'PORT': '',
  75 + 'USER': '',
  76 + 'PASSWORD': '',
  77 + 'OPTIONS': {'init_command': 'SET storage_engine=InnoDB'},
  78 + 'TEST_CHARSET': 'utf8',
  79 + 'TEST_COLLATION': 'utf8_general_ci',
  80 + },
  81 +}
  82 +
  83 +# A database to be used by the services scripts, which does not use Django.
  84 +# The settings can be copied from DATABASES, but since its not a full Django
  85 +# database connection, only some values are supported.
  86 +SERVICES_DATABASE = {
  87 + 'NAME': 'zamboni',
  88 + 'USER': '',
  89 + 'PASSWORD': '',
  90 + 'HOST': '',
  91 +}
  92 +
  93 +DATABASE_ROUTERS = ('multidb.PinningMasterSlaveRouter',)
  94 +
  95 +# For use django-mysql-pool backend.
  96 +DATABASE_POOL_ARGS = {
  97 + 'max_overflow': 10,
  98 + 'pool_size': 5,
  99 + 'recycle': 300
  100 +}
  101 +
  102 +# Put the aliases for your slave databases in this list.
  103 +SLAVE_DATABASES = []
  104 +
  105 +# Local time zone for this installation. Choices can be found here:
  106 +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
  107 +# although not all choices may be available on all operating systems.
  108 +# If running in a Windows environment this must be set to the same as your
  109 +# system time zone.
  110 +TIME_ZONE = 'America/Los_Angeles'
  111 +
  112 +# Language code for this installation. All choices can be found here:
  113 +# http://www.i18nguy.com/unicode/language-identifiers.html
  114 +LANGUAGE_CODE = 'en-US'
  115 +
  116 +# Accepted locales
  117 +# Note: If you update this list, don't forget to also update the locale
  118 +# permissions in the database.
  119 +AMO_LANGUAGES = (
  120 + 'af', 'ar', 'bg', 'ca', 'cs', 'da', 'de', 'el', 'en-US', 'es', 'eu', 'fa',
  121 + 'fi', 'fr', 'ga-IE', 'he', 'hu', 'id', 'it', 'ja', 'ko', 'mn', 'nl', 'pl',
  122 + 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sl', 'sq', 'sv-SE', 'uk', 'vi',
  123 + 'zh-CN', 'zh-TW',
  124 +)
  125 +
  126 +# Explicit conversion of a shorter language code into a more specific one.
  127 +SHORTER_LANGUAGES = {
  128 + 'en': 'en-US', 'ga': 'ga-IE', 'pt': 'pt-PT', 'sv': 'sv-SE', 'zh': 'zh-CN'
  129 +}
  130 +
  131 +# Not shown on the site, but .po files exist and these are available on the
  132 +# L10n dashboard. Generally languages start here and move into AMO_LANGUAGES.
  133 +HIDDEN_LANGUAGES = ('cy', 'sr', 'sr-Latn', 'tr')
  134 +
  135 +
  136 +def lazy_langs(languages):
  137 + from product_details import product_details
  138 + if not product_details.languages:
  139 + return {}
  140 + return dict([(i.lower(), product_details.languages[i]['native'])
  141 + for i in languages])
  142 +
  143 +# Where product details are stored see django-mozilla-product-details
  144 +PROD_DETAILS_DIR = path('product_json')
  145 +
  146 +# Override Django's built-in with our native names
  147 +LANGUAGES = lazy(lazy_langs, dict)(AMO_LANGUAGES)
  148 +RTL_LANGUAGES = ('ar', 'fa', 'fa-IR', 'he')
  149 +
  150 +LANGUAGE_URL_MAP = dict([(i.lower(), i) for i in AMO_LANGUAGES])
  151 +
  152 +# Tower / L10n
  153 +LOCALE_PATHS = (path('locale'),)
  154 +TEXT_DOMAIN = 'messages'
  155 +STANDALONE_DOMAINS = [TEXT_DOMAIN, 'javascript']
  156 +TOWER_KEYWORDS = {
  157 + '_lazy': None,
  158 +}
  159 +TOWER_ADD_HEADERS = True
  160 +
  161 +# If you set this to False, Django will make some optimizations so as not
  162 +# to load the internationalization machinery.
  163 +USE_I18N = True
  164 +
  165 +# The host currently running the site. Only use this in code for good reason;
  166 +# the site is designed to run on a cluster and should continue to support that
  167 +HOSTNAME = socket.gethostname()
  168 +
  169 +# The front end domain of the site. If you're not running on a cluster this
  170 +# might be the same as HOSTNAME but don't depend on that. Use this when you
  171 +# need the real domain.
  172 +DOMAIN = HOSTNAME
  173 +
  174 +# Full base URL for your main site including protocol. No trailing slash.
  175 +# Example: https://addons.mozilla.org
  176 +SITE_URL = 'http://%s' % DOMAIN
  177 +
  178 +# Domain of the services site. This is where your API, and in-product pages
  179 +# live.
  180 +SERVICES_DOMAIN = 'services.%s' % DOMAIN
  181 +
  182 +# Full URL to your API service. No trailing slash.
  183 +# Example: https://services.addons.mozilla.org
  184 +SERVICES_URL = 'http://%s' % SERVICES_DOMAIN
  185 +
  186 +# When True, the addon API should include performance data.
  187 +API_SHOW_PERF_DATA = True
  188 +
  189 +# The domain of the mobile site.
  190 +MOBILE_DOMAIN = 'm.%s' % DOMAIN
  191 +
  192 +# The full url of the mobile site.
  193 +MOBILE_SITE_URL = 'http://%s' % MOBILE_DOMAIN
  194 +
  195 +OAUTH_CALLBACK_VIEW = 'api.views.request_token_ready'
  196 +
  197 +# Absolute path to the directory that holds media.
  198 +# Example: "/home/media/media.lawrence.com/"
  199 +MEDIA_ROOT = path('media')
  200 +
  201 +# URL that handles the media served from MEDIA_ROOT. Make sure to use a
  202 +# trailing slash if there is a path component (optional in other cases).
  203 +# Examples: "http://media.lawrence.com", "http://example.com/media/"
  204 +MEDIA_URL = '/media/'
  205 +
  206 +# Absolute path to a temporary storage area
  207 +TMP_PATH = path('tmp')
  208 +
  209 +# When True, create a URL root /tmp that serves files in your temp path.
  210 +# This is useful for development to view upload pics, etc.
  211 +# NOTE: This only works when DEBUG is also True.
  212 +SERVE_TMP_PATH = False
  213 +
  214 +# Absolute path to a writable directory shared by all servers. No trailing
  215 +# slash. Example: /data/
  216 +NETAPP_STORAGE = TMP_PATH
  217 +
  218 +# File path for storing XPI/JAR files (or any files associated with an
  219 +# add-on). Example: /mnt/netapp_amo/addons.mozilla.org-remora/files
  220 +ADDONS_PATH = NETAPP_STORAGE + '/addons'
  221 +
  222 +# Like ADDONS_PATH but protected by the app. Used for storing files that should
  223 +# not be publicly accessible (like disabled add-ons).
  224 +GUARDED_ADDONS_PATH = NETAPP_STORAGE + '/guarded-addons'
  225 +
  226 +# Used for storing watermarked addons for the app.
  227 +WATERMARKED_ADDONS_PATH = NETAPP_STORAGE + '/watermarked-addons'
  228 +
  229 +# Used for storing signed webapps.
  230 +SIGNED_APPS_PATH = NETAPP_STORAGE + '/signed-apps'
  231 +# Special reviewer signed ones for special people.
  232 +SIGNED_APPS_REVIEWER_PATH = NETAPP_STORAGE + '/signed-apps-reviewer'
  233 +
  234 +# Absolute path to a writable directory shared by all servers. No trailing
  235 +# slash.
  236 +# Example: /data/uploads
  237 +UPLOADS_PATH = NETAPP_STORAGE + '/uploads'
  238 +
  239 +DEFAULT_APP = 'firefox'
  240 +# File path for add-on files that get rsynced to mirrors.
  241 +# /mnt/netapp_amo/addons.mozilla.org-remora/public-staging
  242 +MIRROR_STAGE_PATH = NETAPP_STORAGE + '/public-staging'
  243 +
  244 +
  245 +# paths that don't require a locale prefix
  246 +SUPPORTED_NONLOCALES = ('google1f3e37b7351799a5.html', 'img', 'media',
  247 + 'robots.txt', 'services', 'downloads', 'blocklist')
  248 +
  249 +# Make this unique, and don't share it with anybody.
  250 +SECRET_KEY = 'r#%9w^o_80)7f%!_ir5zx$tu3mupw9u%&s!)-_q%gy7i+fhx#)'
  251 +
  252 +# Templates
  253 +
  254 +# List of callables that know how to import templates from various sources.
  255 +TEMPLATE_LOADERS = (
  256 + #'jingo.Loader',
  257 + 'django.template.loaders.filesystem.Loader',
  258 + 'django.template.loaders.app_directories.Loader',
  259 +)
  260 +
  261 +TEMPLATE_CONTEXT_PROCESSORS = (
  262 + 'django.contrib.auth.context_processors.auth',
  263 + 'django.core.context_processors.debug',
  264 + 'django.core.context_processors.media',
  265 + 'django.core.context_processors.request',
  266 +# 'session_csrf.context_processor',
  267 +
  268 + 'django.contrib.messages.context_processors.messages',
  269 + 'jingo_minify.helpers.build_ids',
  270 +)
  271 +
  272 +TEMPLATE_DIRS = (
  273 + path('templates'),
  274 +)
  275 +
  276 +
  277 +def JINJA_CONFIG():
  278 + import jinja2
  279 + from django.conf import settings
  280 + from django.core.cache import cache
  281 + config = {'extensions': ['tower.template.i18n',
  282 + 'jinja2.ext.do',
  283 + 'jinja2.ext.with_', 'jinja2.ext.loopcontrols'],
  284 + 'finalize': lambda x: x if x is not None else ''}
  285 + if False and not settings.DEBUG:
  286 + # We're passing the _cache object directly to jinja because
  287 + # Django can't store binary directly; it enforces unicode on it.
  288 + # Details: http://jinja.pocoo.org/2/documentation/api#bytecode-cache
  289 + # and in the errors you get when you try it the other way.
  290 + bc = jinja2.MemcachedBytecodeCache(cache._cache,
  291 + "%sj2:" % settings.CACHE_PREFIX)
  292 + config['cache_size'] = -1 # Never clear the cache
  293 + config['bytecode_cache'] = bc
  294 + return config
  295 +
  296 +
  297 +MIDDLEWARE_CLASSES = (
  298 + 'django.contrib.sessions.middleware.SessionMiddleware',
  299 + 'django.contrib.auth.middleware.AuthenticationMiddleware',
  300 + 'django.middleware.csrf.CsrfViewMiddleware',
  301 +)
  302 +
  303 +# Auth
  304 +AUTHENTICATION_BACKENDS = (
  305 + 'django_browserid.auth.BrowserIDBackend',
  306 + 'gelato.models.users.AmoUserBackend',
  307 + 'cake.backends.SessionBackend',
  308 +)
  309 +AUTH_PROFILE_MODULE = 'users.UserProfile'
  310 +
  311 +ROOT_URLCONF = 'gelato.admin.urls'
  312 +
  313 +INSTALLED_APPS = (
  314 + 'gelato.admin',
  315 + 'addons',
  316 + 'gelato.translations',
  317 + 'translations',
  318 + 'applications',
  319 + 'versions',
  320 + 'users',
  321 + # Third party apps
  322 + #'djcelery',
  323 + 'django_extensions',
  324 + 'django_nose',
  325 + 'raven.contrib.django',
  326 + #'gunicorn',
  327 + #'piston',
  328 + 'waffle',
  329 +
  330 + # Django contrib apps
  331 + 'django.contrib.staticfiles',
  332 + 'django.contrib.admin',
  333 + 'django.contrib.auth',
  334 + 'django.contrib.contenttypes',
  335 + 'django.contrib.messages',
  336 + 'django.contrib.sessions',
  337 +
  338 + # Has to load after auth
  339 + #'django_browserid',
  340 + #'django_statsd',
  341 + #'radagast',
  342 +)
  343 +
  344 +# These apps will be removed from INSTALLED_APPS in a production environment.
  345 +DEV_APPS = (
  346 + 'django_nose',
  347 +)
  348 +
  349 +# Tests
  350 +TEST_RUNNER = 'test_utils.runner.RadicalTestSuiteRunner'
  351 +NOSE_ARGS = [
  352 + '--with-fixture-bundling',
  353 + '--exclude=mkt/*',
  354 +]
  355 +
  356 +# If you want to run Selenium tests, you'll need to have a server running.
  357 +# Then give this a dictionary of settings. Something like:
  358 +# 'HOST': 'localhost',
  359 +# 'PORT': 4444,
  360 +# 'BROWSER': '*firefox', # Alternative: *safari
  361 +SELENIUM_CONFIG = {}
  362 +
  363 +# Tells the extract script what files to look for l10n in and what function
  364 +# handles the extraction. The Tower library expects this.
  365 +DOMAIN_METHODS = {
  366 + 'messages': [
  367 + ('apps/**.py',
  368 + 'tower.management.commands.extract.extract_tower_python'),
  369 + ('apps/**/templates/**.html',
  370 + 'tower.management.commands.extract.extract_tower_template'),
  371 + ('templates/**.html',
  372 + 'tower.management.commands.extract.extract_tower_template'),
  373 + ('mkt/**.py',
  374 + 'tower.management.commands.extract.extract_tower_python'),
  375 + ('mkt/**/templates/**.html',
  376 + 'tower.management.commands.extract.extract_tower_template'),
  377 + ('mkt/templates/**.html',
  378 + 'tower.management.commands.extract.extract_tower_template'),
  379 + ],
  380 + 'lhtml': [
  381 + ('**/templates/**.lhtml',
  382 + 'tower.management.commands.extract.extract_tower_template'),
  383 + ],
  384 + 'javascript': [
  385 + # We can't say **.js because that would dive into mochikit and timeplot
  386 + # and all the other baggage we're carrying. Timeplot, in particular,
  387 + # crashes the extractor with bad unicode data.
  388 + ('media/js/*.js', 'javascript'),
  389 + ('media/js/amo2009/**.js', 'javascript'),
  390 + ('media/js/impala/**.js', 'javascript'),
  391 + ('media/js/zamboni/**.js', 'javascript'),
  392 + ('media/js/mkt/**.js', 'javascript'),
  393 + ],
  394 +}
  395 +
  396 +# Bundles is a dictionary of two dictionaries, css and js, which list css files
  397 +# and js files that can be bundled together by the minify app.
  398 +MINIFY_BUNDLES = {
  399 + 'css': {
  400 + # CSS files common to the entire site.
  401 + 'zamboni/css': (
  402 + 'css/legacy/main.css',
  403 + 'css/legacy/main-mozilla.css',
  404 + 'css/legacy/jquery-lightbox.css',
  405 + 'css/legacy/autocomplete.css',
  406 + 'css/zamboni/zamboni.css',
  407 + 'css/global/headerfooter.css',
  408 + 'css/zamboni/tags.css',
  409 + 'css/zamboni/tabs.css',
  410 + 'css/impala/formset.less',
  411 + 'css/impala/suggestions.less',
  412 + 'css/impala/header.less',
  413 + 'css/impala/moz-tab.css',
  414 + 'css/impala/footer.less',
  415 + 'css/impala/faux-zamboni.less',
  416 + 'css/impala/collection-stats.less',
  417 + ),
  418 + 'zamboni/impala': (
  419 + 'css/impala/base.css',
  420 + 'css/legacy/jquery-lightbox.css',
  421 + 'css/impala/site.less',
  422 + 'css/impala/typography.less',
  423 + 'css/global/headerfooter.css',
  424 + 'css/impala/forms.less',
  425 + 'css/common/invisible-upload.less',
  426 + 'css/impala/header.less',
  427 + 'css/impala/footer.less',
  428 + 'css/impala/moz-tab.css',
  429 + 'css/impala/hovercards.less',
  430 + 'css/impala/toplist.less',
  431 + 'css/impala/carousel.less',
  432 + 'css/impala/reviews.less',
  433 + 'css/impala/buttons.less',
  434 + 'css/impala/promos.less',
  435 + 'css/impala/addon_details.less',
  436 + 'css/impala/policy.less',
  437 + 'css/impala/expando.less',
  438 + 'css/impala/popups.less',
  439 + 'css/impala/l10n.less',
  440 + 'css/impala/contributions.less',
  441 + 'css/impala/lightbox.less',
  442 + 'css/impala/prose.less',
  443 + 'css/impala/sharing.less',
  444 + 'css/impala/abuse.less',
  445 + 'css/impala/paginator.less',
  446 + 'css/impala/listing.less',
  447 + 'css/impala/versions.less',
  448 + 'css/impala/users.less',
  449 + 'css/impala/collections.less',
  450 + 'css/impala/tooltips.less',
  451 + 'css/impala/search.less',
  452 + 'css/impala/suggestions.less',
  453 + 'css/impala/colorpicker.less',
  454 + 'css/impala/personas.less',
  455 + 'css/impala/login.less',
  456 + 'css/impala/dictionaries.less',
  457 + 'css/impala/apps.less',
  458 + 'css/impala/formset.less',
  459 + 'css/impala/tables.less',
  460 + 'css/impala/compat.less',
  461 + 'css/impala/localizers.less',
  462 + ),
  463 + 'zamboni/stats': (
  464 + 'css/impala/stats.less',
  465 + ),
  466 + 'zamboni/discovery-pane': (
  467 + 'css/zamboni/discovery-pane.css',
  468 + 'css/impala/promos.less',
  469 + 'css/legacy/jquery-lightbox.css',
  470 + ),
  471 + 'zamboni/devhub': (
  472 + 'css/impala/tooltips.less',
  473 + 'css/zamboni/developers.css',
  474 + 'css/zamboni/docs.less',
  475 + 'css/impala/developers.less',
  476 + 'css/devhub/packager.less',
  477 + 'css/devhub/listing.less',
  478 + 'css/devhub/popups.less',
  479 + 'css/devhub/compat.less',
  480 + 'css/impala/formset.less',
  481 + 'css/devhub/forms.less',
  482 + 'css/common/invisible-upload.less',
  483 + 'css/devhub/submission.less',
  484 + 'css/devhub/refunds.less',
  485 + 'css/devhub/buttons.less',
  486 + 'css/devhub/in-app-config.less',
  487 + ),
  488 + 'zamboni/devhub_impala': (
  489 + 'css/impala/developers.less',
  490 + 'css/devhub/listing.less',
  491 + 'css/devhub/popups.less',
  492 + 'css/devhub/compat.less',
  493 + 'css/devhub/dashboard.less',
  494 + 'css/devhub/forms.less',
  495 + 'css/common/invisible-upload.less',
  496 + 'css/devhub/submission.less',
  497 + 'css/devhub/search.less',
  498 + 'css/devhub/refunds.less',
  499 + ),
  500 + 'zamboni/editors': (
  501 + 'css/zamboni/editors.css',
  502 + ),
  503 + 'zamboni/files': (
  504 + 'css/lib/syntaxhighlighter/shCoreDefault.css',
  505 + 'css/zamboni/files.css',
  506 + ),
  507 + 'zamboni/mobile': (
  508 + 'css/zamboni/mobile.css',
  509 + 'css/mobile/typography.less',
  510 + 'css/mobile/forms.less',
  511 + 'css/mobile/header.less',
  512 + 'css/mobile/search.less',
  513 + 'css/mobile/listing.less',
  514 + 'css/mobile/footer.less',
  515 + ),
  516 + 'zamboni/admin': (
  517 + 'css/zamboni/admin-django.css',
  518 + 'css/zamboni/admin-mozilla.css',
  519 + 'css/zamboni/admin_features.css'
  520 + ),
  521 + },
  522 + 'js': {
  523 + # JS files common to the entire site (pre-impala).
  524 + 'common': (
  525 + 'js/lib/jquery-1.6.4.js',
  526 + 'js/lib/underscore.js',
  527 + 'js/zamboni/browser.js',
  528 + 'js/amo2009/addons.js',
  529 + 'js/zamboni/init.js',
  530 + 'js/impala/capabilities.js',
  531 + 'js/lib/format.js',
  532 + 'js/lib/jquery.cookie.js',
  533 + 'js/zamboni/storage.js',
  534 + 'js/zamboni/apps.js',
  535 + 'js/zamboni/buttons.js',
  536 + 'js/zamboni/tabs.js',
  537 + 'js/common/keys.js',
  538 +
  539 + # jQuery UI
  540 + 'js/lib/jquery-ui/jquery.ui.core.js',
  541 + 'js/lib/jquery-ui/jquery.ui.position.js',
  542 + 'js/lib/jquery-ui/jquery.ui.widget.js',
  543 + 'js/lib/jquery-ui/jquery.ui.mouse.js',
  544 + 'js/lib/jquery-ui/jquery.ui.autocomplete.js',
  545 + 'js/lib/jquery-ui/jquery.ui.datepicker.js',
  546 + 'js/lib/jquery-ui/jquery.ui.sortable.js',
  547 +
  548 + 'js/zamboni/helpers.js',
  549 + 'js/zamboni/global.js',
  550 + 'js/amo2009/global.js',
  551 + 'js/common/ratingwidget.js',
  552 + 'js/lib/jquery-ui/jqModal.js',
  553 + 'js/zamboni/l10n.js',
  554 + 'js/zamboni/debouncer.js',
  555 +
  556 + # Homepage
  557 + 'js/impala/promos.js',
  558 + 'js/zamboni/homepage.js',
  559 +
  560 + # Add-ons details page
  561 + 'js/lib/jquery-ui/ui.lightbox.js',
  562 + 'js/get-satisfaction-v2.js',
  563 + 'js/zamboni/contributions.js',
  564 + 'js/zamboni/addon_details.js',
  565 + 'js/impala/abuse.js',
  566 + 'js/zamboni/reviews.js',
  567 +
  568 + # Personas
  569 + 'js/lib/jquery.hoverIntent.js',
  570 + 'js/zamboni/personas_core.js',
  571 + 'js/zamboni/personas.js',
  572 +
  573 + # Collections
  574 + 'js/zamboni/collections.js',
  575 +
  576 + # Performance
  577 + 'js/zamboni/perf.js',
  578 +
  579 + # Users
  580 + 'js/zamboni/users.js',
  581 +
  582 + # Fix-up outgoing links
  583 + 'js/zamboni/outgoing_links.js',
  584 +
  585 + # Hover delay for global header
  586 + 'js/global/menu.js',
  587 +
  588 + # Password length and strength
  589 + 'js/zamboni/password-strength.js',
  590 +
  591 + # Search suggestions
  592 + 'js/impala/forms.js',
  593 + 'js/impala/ajaxcache.js',
  594 + 'js/impala/suggestions.js',
  595 + 'js/impala/site_suggestions.js',
  596 + ),
  597 +
  598 + # Impala: Things to be loaded at the top of the page
  599 + 'preload': (
  600 + 'js/lib/jquery-1.6.4.js',
  601 + 'js/impala/preloaded.js'
  602 + ),
  603 + # Impala: Things to be loaded at the bottom
  604 + 'impala': (
  605 + 'js/lib/underscore.js',
  606 + 'js/impala/carousel.js',
  607 + 'js/zamboni/browser.js',
  608 + 'js/amo2009/addons.js',
  609 + 'js/zamboni/init.js',
  610 + 'js/impala/capabilities.js',
  611 + 'js/lib/format.js',
  612 + 'js/lib/jquery.cookie.js',
  613 + 'js/zamboni/storage.js',
  614 + 'js/zamboni/apps.js',
  615 + 'js/zamboni/buttons.js',
  616 + 'js/lib/jquery.pjax.js',
  617 + 'js/impala/footer.js',
  618 + 'js/common/keys.js',
  619 +
  620 + # BrowserID
  621 + 'js/zamboni/browserid_support.js',
  622 +
  623 + # jQuery UI
  624 + 'js/lib/jquery-ui/jquery.ui.core.js',
  625 + 'js/lib/jquery-ui/jquery.ui.position.js',
  626 + 'js/lib/jquery-ui/jquery.ui.widget.js',
  627 + 'js/lib/jquery-ui/jquery.ui.mouse.js',
  628 + 'js/lib/jquery-ui/jquery.ui.autocomplete.js',
  629 + 'js/lib/jquery-ui/jquery.ui.datepicker.js',
  630 + 'js/lib/jquery-ui/jquery.ui.sortable.js',
  631 +
  632 + 'js/zamboni/truncation.js',
  633 + 'js/impala/ajaxcache.js',
  634 + 'js/zamboni/helpers.js',
  635 + 'js/zamboni/global.js',
  636 + 'js/impala/global.js',
  637 + 'js/common/ratingwidget.js',
  638 + 'js/lib/jquery-ui/jqModal.js',
  639 + 'js/zamboni/l10n.js',
  640 + 'js/impala/forms.js',
  641 +
  642 + # Homepage
  643 + 'js/impala/promos.js',
  644 + 'js/impala/homepage.js',
  645 +
  646 + # Add-ons details page
  647 + 'js/lib/jquery-ui/ui.lightbox.js',
  648 + 'js/get-satisfaction-v2.js',
  649 + 'js/zamboni/contributions.js',
  650 + 'js/impala/addon_details.js',
  651 + 'js/impala/abuse.js',
  652 + 'js/impala/reviews.js',
  653 +
  654 + # Browse listing pages
  655 + 'js/impala/listing.js',
  656 +
  657 + # Personas
  658 + 'js/lib/jquery.hoverIntent.js',
  659 + 'js/zamboni/personas_core.js',
  660 + 'js/zamboni/personas.js',
  661 +
  662 + # Persona creation
  663 + 'js/common/upload-image.js',
  664 + 'js/lib/jquery.minicolors.js',
  665 + 'js/impala/persona_creation.js',
  666 +
  667 + # Collections
  668 + 'js/zamboni/collections.js',
  669 + 'js/impala/collections.js',
  670 +
  671 + # Performance
  672 + 'js/zamboni/perf.js',
  673 +
  674 + # Users
  675 + 'js/zamboni/users.js',
  676 + 'js/impala/users.js',
  677 +
  678 + # Search
  679 + 'js/impala/serializers.js',
  680 + 'js/impala/search.js',
  681 + 'js/impala/suggestions.js',
  682 + 'js/impala/site_suggestions.js',
  683 +
  684 + # Login
  685 + 'js/impala/login.js',
  686 +
  687 + # Fix-up outgoing links
  688 + 'js/zamboni/outgoing_links.js',
  689 + 'js/lib/stick.js',
  690 + ),
  691 + 'zamboni/discovery': (
  692 + 'js/lib/jquery-1.6.4.js',
  693 + 'js/lib/underscore.js',
  694 + 'js/zamboni/browser.js',
  695 + 'js/zamboni/init.js',
  696 + 'js/impala/capabilities.js',
  697 + 'js/lib/format.js',
  698 + 'js/impala/carousel.js',
  699 +
  700 + # Add-ons details
  701 + 'js/lib/jquery.cookie.js',
  702 + 'js/zamboni/storage.js',
  703 + 'js/zamboni/buttons.js',
  704 + 'js/lib/jquery-ui/ui.lightbox.js',
  705 +
  706 + # Personas