Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e5a536a
Start buildbot integration.
jeremydw Jun 8, 2015
b7189be
Initial work on domain visibility.
jeremydw Aug 26, 2015
13bbb1a
Domains fix.
jeremydw Aug 31, 2015
cf0f7a1
Visibility fix.
jeremydw Sep 1, 2015
c569657
Fix avatars.
jeremydw Sep 1, 2015
540e63b
Work on domains.
jeremydw Nov 2, 2015
92a2db4
Initial buildbot integration.
jeremydw Nov 4, 2015
0a0b6ac
Merge.
jeremydw Nov 4, 2015
651642b
Add translations and catalogs.
jeremydw Nov 4, 2015
2a53e33
Add catalog services.
jeremydw Nov 4, 2015
ffb2cab
Fix catalogs service.
jeremydw Nov 5, 2015
7bf24a5
Update buildbot job when git url changes.
jeremydw Nov 5, 2015
61010c1
Work on buildbot integration.
jeremydw Nov 9, 2015
7717a21
Work on translations.
jeremydw Nov 10, 2015
9fa8af8
Buildbot catalog updating.
jeremydw Nov 11, 2015
7d89f1a
Work on translations and staging.
jeremydw Nov 11, 2015
3306dcc
Use jobs service to list branches rather than restfulgit.
jeremydw Nov 11, 2015
83930ce
Remove dead code.
jeremydw Nov 11, 2015
e8bb726
Work on catalogs.
jeremydw Nov 11, 2015
3c5278c
Work on groups.
jeremydw Nov 11, 2015
5526a6b
Groups and projects. Clean up.
jeremydw Nov 11, 2015
51e2a88
Get policies working.
jeremydw Nov 12, 2015
32af7b5
Use policies on service.
jeremydw Nov 12, 2015
efe3e7a
Replace legacy can with policies.
jeremydw Nov 12, 2015
61002e5
Delete teams in favor of groups.
jeremydw Nov 12, 2015
14d7603
Raise membership conflict errors.
jeremydw Nov 12, 2015
b556c56
Add subdomain.
jeremydw Nov 12, 2015
32257c6
jetway -> app
jeremydw Nov 17, 2015
7b82aa7
Delete dead frontend.
jeremydw Nov 17, 2015
20b0a3f
Add translation branch support.
jeremydw Nov 17, 2015
ec7ee87
Group memberships.
jeremydw Nov 18, 2015
5e43ab2
Add refs to translations service.
jeremydw Nov 19, 2015
0774120
Remove frontend deps.
jeremydw Nov 29, 2015
359a727
Add webreview-fe as a submodule.
jeremydw Nov 29, 2015
f2abd33
Serve webreview-fe app.
jeremydw Nov 29, 2015
9e2d304
Improve ember app build integration. Fix avatars on versioned URLs.
jeremydw Dec 1, 2015
3a61f96
Add transfer owner method to projects.
jeremydw Dec 11, 2015
a7e28d9
Work on project transfers.
jeremydw May 28, 2016
13f7560
Org groups.
jeremydw May 28, 2016
f0bec97
Org owners.
jeremydw May 29, 2016
1d7b240
Add org owner projects to search results.
jeremydw May 29, 2016
b71f444
Work on buildbot.
jeremydw Feb 21, 2017
13e9dca
Work on ember migration.
jeremydw Mar 19, 2017
d6859f5
Clean up dead code.
jeremydw Mar 19, 2017
d1544d4
Add Makefile. Work on users/projects/groups.
jeremydw Mar 19, 2017
8171cae
Update indexes.
jeremydw Mar 19, 2017
b4a8e83
Work on groups.
jeremydw Mar 20, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "webreview-fe"]
path = webreview-fe
url = https://github.com/grow/webreview-fe
3 changes: 0 additions & 3 deletions Dockerfile

This file was deleted.

55 changes: 55 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version ?= auto
project ?= betawebreview

run-frontend:
cd webreview-fe && ember serve

run-backend:
virtualenv env
. env/bin/activate
dev_appserver.py \
--port=8088 .

install:
virtualenv env
. env/bin/activate
./env/bin/pip install \
--upgrade \
--allow-unverified dateutil \
--allow-external dateutil \
-r \
requirements.txt
./env/bin/gaenv --lib lib --no-import

test:
. env/bin/activate
./env/bin/nosetests \
-v \
--rednose \
--nocapture \
--with-gae \
--gae-lib-root=$(HOME)/google_appengine \
--with-coverage \
--cover-erase \
--cover-html \
--cover-html-dir=htmlcov \
--cover-package=app \
app/

deploy:
$(MAKE) test
cd webreview-fe && ember build && cd ..
gcloud app deploy \
-q \
--verbosity=error \
--project=$(project) \
--version=$(version) \
--no-promote \
app.yaml
gcloud app deploy \
-q \
--no-promote \
--verbosity=error \
--project=$(project) \
--version=$(version) \
index.yaml
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Run the below command and follow the on-screen instructions to install dependenc

./scripts/setup

1. The Google App Engine SDK is required. Currently, the version packaged with the gcloud SDK is not compatible with the test runner, so you'll have to download the [standalone GoogleAppEngineLauncher](https://cloud.google.com/appengine/downloads).
1. Run `./scripts/test` to verify tests pass.
1. Run `./scripts/run` to start a development server.

Expand Down
32 changes: 18 additions & 14 deletions app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ api_version: 1
runtime: python27
threadsafe: true

instance_class: F4_1G

env_variables:
GAE_USE_SOCKETS_HTTPLIB: 'anyvalue' # https://github.com/shazow/urllib3/issues/618#issuecomment-101795512
JETWAY_CONFIG: config/jetway.googwebreview.yaml

libraries:
- name: lxml
version: latest
- name: endpoints
version: latest
- name: ssl
Expand All @@ -26,22 +34,13 @@ handlers:
secure: always

- url: /_ah/spi/.*
script: jetway.main.endpoints_app

- url: /_jetway/[^/]*/static/css
static_dir: dist/css
script: app.main.endpoints_app

- url: /_jetway/[^/]*/static/js
static_dir: dist/js

- url: /_jetway/[^/]*/static/html
static_dir: jetway/frontend/static/html

- url: /_jetway/[^/]*/static/images
static_dir: jetway/frontend/static/images
- url: /_webreview/assets
static_dir: dist/assets

- url: /.*
script: jetway.main.app
script: app.main.app

skip_files:
- ^(.*/)?#.*#
Expand All @@ -55,10 +54,15 @@ skip_files:
- ^(.*/)?index\.yaml
- ^(.*/)?index\.yml
- ^(.*/)?run_tests.py
- ^.*.example
- ^.*bower_components.*
- ^.*node_modules.*
- ^.*tmp.*
- bower_components
- env
- htmlconv
- lib/Crypto
- lib/PIL
- node_modules
- testing
- ^.*.example
- webreview-fe
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion jetway/api_errors.py → app/api_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import httplib


class Error(Exception):
class Error(remote.ApplicationError):
pass


Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion jetway/auth/handlers.py → app/auth/handlers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from apiclient import discovery
from google.appengine.api import memcache
from jetway.users import users
from app.users import users
from oauth2client import appengine
from webapp2_extras import auth as webapp2_auth
from webapp2_extras import security
Expand Down
File renamed without changes.
13 changes: 8 additions & 5 deletions jetway/avatars/avatars.py → app/avatars/avatars.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from google.appengine.ext import blobstore
from google.appengine.ext import ndb
from jetway.files import files
from jetway.files import messages as file_messages
from app.files import files
from app.files import messages as file_messages
import appengine_config
import datetime
import time
Expand Down Expand Up @@ -65,7 +65,8 @@ def create_upload_url(cls, entity):
letter = entity.key.kind()[:1].lower()
avatar_ident = '{}/{}'.format(letter, entity.ident)
root = '{}/jetway/avatars/{}'.format(gcs_bucket, avatar_ident)
return blobstore.create_upload_url('/avatars/{}'.format(avatar_ident), gs_bucket_name=root)
return blobstore.create_upload_url(
'/avatars/{}'.format(avatar_ident), gs_bucket_name=root)

def update(self, gs_object_name):
if self.gs_basename:
Expand All @@ -80,9 +81,11 @@ def create_url(cls, owner):
return path
num = owner.ident[0]
scheme = os.getenv('wsgi.url_scheme')
hostname = os.getenv('DEFAULT_VERSION_HOSTNAME')
hostname = os.getenv('HTTP_HOST')
sep = '.' if scheme == 'http' else '-dot-'
return '//avatars{}{}{}{}'.format(num, sep, hostname, path)
if '-dot-' in hostname:
return '//{}{}'.format(hostname, path)
return '//avatars-{}{}{}{}'.format(num, sep, hostname, path)

@classmethod
def generate(cls, ident):
Expand Down
4 changes: 2 additions & 2 deletions jetway/avatars/messages.py → app/avatars/messages.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from protorpc import messages
from jetway.owners import messages as owner_messages
from jetway.projects import messages as project_messages
from app.owners import messages as owner_messages
from app.projects import messages as project_messages


class CreateUploadUrlRequest(messages.Message):
Expand Down
6 changes: 3 additions & 3 deletions jetway/avatars/services.py → app/avatars/services.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from protorpc import remote
from jetway import api
from jetway.avatars import avatars
from jetway.avatars import messages
from app import api
from app.avatars import avatars
from app.avatars import messages


class AvatarService(api.Service):
Expand Down
File renamed without changes.
110 changes: 110 additions & 0 deletions app/buildbot/buildbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from requests import auth
import appengine_config
import requests

BASE = '{}/api'.format(appengine_config.BUILDBOT_URL)

VERIFY = False


class Error(Exception):
pass


class ConnectionError(Error):
pass


class IntegrationError(Error):
pass


class Buildbot(object):

@property
def env(self):
return {
'WEBREVIEW_API_KEY': appengine_config.BUILDBOT_API_KEY,
}

@property
def auth(self):
return auth.HTTPBasicAuth(
appengine_config.BUILDBOT_USERNAME,
appengine_config.BUILDBOT_PASSWORD)

def create_job(self, git_url, remote):
data = {
'git_url': git_url,
'remote': remote,
'env': self.env,
}
try:
resp = requests.post(BASE + '/jobs', json=data, auth=self.auth,
verify=VERIFY)
resp.raise_for_status()
except Exception as e:
raise ConnectionError(e)
content = resp.json()
if 'error' in content:
raise IntegrationError(content['error'])
return content

def get_job(self, job_id):
try:
resp = requests.get(BASE + '/jobs/{}'.format(job_id), auth=self.auth,
verify=VERIFY)
resp.raise_for_status()
except Exception as e:
raise ConnectionError(e)
content = resp.json()
if 'error' in content:
raise IntegrationError(content['error'])
return content

def get_contents(self, job_id, path=None, ref=None):
path = path or '/'
try:
request_path = BASE + '/git/repos/{}/contents{}'.format(job_id, path)
resp = requests.get(request_path, auth=self.auth, verify=VERIFY)
resp.raise_for_status()
except Exception as e:
raise ConnectionError(e)
content = resp.json()
if 'error' in content:
raise IntegrationError(content['error'])
return content

def read_file(self, job_id, path, ref):
try:
request_path = BASE + '/git/repos/{}/raw/{}{}'.format(job_id, ref, path)
resp = requests.get(request_path, auth=self.auth, verify=VERIFY)
resp.raise_for_status()
except Exception as e:
raise ConnectionError(e)
return resp.content

def write_file(self, job_id, path, contents, message, ref, sha,
committer, author):
data = {
'branch': ref,
'path': path,
'message': message,
'content': contents,
'sha': sha,
'committer': committer,
'author': author,
}
try:
resp = requests.post(
BASE + '/jobs/{}/contents/update'.format(job_id),
json=data,
auth=self.auth,
verify=VERIFY)
resp.raise_for_status()
except Exception as e:
raise ConnectionError(e)
result = resp.json()
if 'error' in result:
raise IntegrationError(result['error'])
return result
11 changes: 11 additions & 0 deletions app/buildbot/messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from protorpc import messages


class CommitMessage(messages.Message):
sha = messages.StringField(1)


class BranchMessage(messages.Message):
name = messages.StringField(1)
commit = messages.MessageField(CommitMessage, 2)
ident = messages.StringField(3)
1 change: 1 addition & 0 deletions app/catalogs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import babel_compatibility_patch
64 changes: 64 additions & 0 deletions app/catalogs/babel_compatibility_patch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from babel import localedata
import pickle
import os

# NOTE: Babel does not support "fuzzy" locales. A locale is considered "fuzzy"
# when a corresponding "localedata" file that matches a given locale's full
# identifier (e.g. "en_US") does not exist. Here's one example: "en_BD". CLDR
# does not have a localedata file matching "en_BD" (English in Bangladesh), but
# it does have individual files for "en" and also "bn_BD". As it turns
# out, localedata files that correspond to a locale's full identifier (e.g.
# "bn_BD.dat") are actually pretty light on the content (largely containing
# things like start-of-week information) and most of the "meat" of the data is
# contained in the main localedata file, e.g. "en.dat".
#
# Users may need to generate pages corresponding to locales that we don't
# have full localedata for, and until Babel supports fuzzy locales, we'll
# monkeypatch two Babel functions to provide partial support for fuzzy locales.
#
# With this monkeypatch, locales will be valid even if Babel doesn't have a
# localedata file matching a locale's full identifier, but locales will still
# fail with a ValueError if the user specifies a territory that does not exist.
# With this patch, a user can, however, specify an invalid language. Obviously,
# this patch should be removed when/if Babel adds support for fuzzy locales.
# Optionally, we may want to provide users with more control over whether a
# locale is valid or invalid, but we can revisit that later.

# See: https://github.com/grow/pygrow/issues/93


def fuzzy_load(name, merge_inherited=True):
localedata._cache_lock.acquire()
try:
data = localedata._cache.get(name)
if not data:
# Load inherited data
if name == 'root' or not merge_inherited:
data = {}
else:
parts = name.split('_')
if len(parts) == 1:
parent = 'root'
else:
parent = '_'.join(parts[:-1])
data = fuzzy_load(parent).copy()
filename = os.path.join(localedata._dirname, '%s.dat' % name)
try:
fileobj = open(filename, 'rb')
try:
if name != 'root' and merge_inherited:
localedata.merge(data, pickle.load(fileobj))
else:
data = pickle.load(fileobj)
localedata._cache[name] = data
finally:
fileobj.close()
except IOError:
pass
return data
finally:
localedata._cache_lock.release()


localedata.exists = lambda name: True
localedata.load = fuzzy_load
Loading