This repository has been archived by the owner on Aug 16, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 36
/
fabfile.py
214 lines (164 loc) · 5.24 KB
/
fabfile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#!/usr/bin/env python
from glob import glob
import os
from fabric.api import *
import app
import app_config
"""
Template-specific functions
Changing the template functions should produce output
with fab render without any exceptions. Any file used
by the site templates should be rendered by fab render.
"""
def less():
"""
Render LESS files to CSS.
"""
for path in glob('less/*.less'):
filename = os.path.split(path)[-1]
name = os.path.splitext(filename)[0]
out_path = 'www/css/%s.less.css' % name
local('node_modules/bin/lessc %s %s' % (path, out_path))
def jst():
"""
Render Underscore templates to a JST package.
"""
local('node_modules/bin/jst --template underscore jst www/js/templates.js')
def download_copy():
"""
Downloads a Google Doc as an .xls file.
"""
base_url = 'https://docs.google.com/spreadsheets/d/%s/export?format=xlsx&id=%s'
doc_url = base_url % (app_config.COPY_GOOGLE_DOC_KEY, app_config.COPY_GOOGLE_DOC_KEY)
local('curl -o data/copy.xlsx "%s"' % doc_url)
def update_copy():
"""
Fetches the latest Google Doc and updates local JSON.
"""
download_copy()
def app_config_js():
"""
Render app_config.js to file.
"""
from app import _app_config_js
response = _app_config_js()
js = response[0]
with open('www/js/app_config.js', 'w') as f:
f.write(js)
def copy_js():
"""
Render copy.js to file.
"""
from app import _copy_js
response = _copy_js()
js = response[0]
with open('www/js/copy.js', 'w') as f:
f.write(js)
def render():
"""
Render HTML templates and compile assets.
"""
from flask import g
update_copy()
less()
jst()
app_config_js()
copy_js()
compiled_includes = []
for rule in app.app.url_map.iter_rules():
rule_string = rule.rule
name = rule.endpoint
if name == 'static' or name.startswith('_'):
print 'Skipping %s' % name
continue
if rule_string.endswith('/'):
filename = 'www' + rule_string + 'index.html'
elif rule_string.endswith('.html'):
filename = 'www' + rule_string
else:
print 'Skipping %s' % name
continue
dirname = os.path.dirname(filename)
if not (os.path.exists(dirname)):
os.makedirs(dirname)
print 'Rendering %s' % (filename)
with app.app.test_request_context(path=rule_string):
g.compile_includes = True
g.compiled_includes = compiled_includes
view = app.__dict__[name]
content = view()
compiled_includes = g.compiled_includes
with open(filename, 'w') as f:
f.write(content.encode('utf-8'))
def tests():
"""
Run Python unit tests.
"""
local('nosetests')
"""
Deployment
Changes to deployment requires a full-stack test. Deployment
has two primary functions: Pushing flat files to S3 and deploying
code to a remote server if required.
"""
def _deploy_to_file_server(path='www'):
local('rm -rf %s/live-data' % path)
local('rm -rf %s/sitemap.xml' % path)
local('rsync -vr %s/ ubuntu@%s:~/www/%s' % (path, app_config.FILE_SERVER, app_config.PROJECT_SLUG))
def assets_down(path='www/assets'):
"""
Download assets folder from s3 to www/assets
"""
local('aws s3 sync s3://%s/%s/ %s/ --acl "public-read" --cache-control "max-age=5" --region "us-east-1"' % (app_config.ASSETS_S3_BUCKET, app_config.PROJECT_SLUG, path))
def assets_up(path='www/assets'):
"""
Upload www/assets folder to s3
"""
_confirm("You are about to replace the copy of the folder on the server with your own copy. Are you sure?")
local('aws s3 sync %s/ s3://%s/%s/ --acl "public-read" --cache-control "max-age=5" --region "us-east-1" --delete' % (
path,
app_config.ASSETS_S3_BUCKET,
app_config.PROJECT_SLUG
))
def assets_rm(path):
"""
remove an asset from s3 and locally
"""
file_list = glob(path)
if len(file_list) > 0:
_confirm("You are about to destroy %s files. Are you sure?" % len(file_list))
with settings(warn_only=True):
for file_path in file_list:
local('aws s3 rm s3://%s/%s/%s --region "us-east-1"' % (
app_config.ASSETS_S3_BUCKET,
app_config.PROJECT_SLUG,
file_path.replace('www/assets/', '')
))
local('rm -rf %s' % path)
def _gzip(in_path='www', out_path='.gzip'):
"""
Gzips everything in www and puts it all in gzip
"""
local('python gzip_assets.py %s %s' % (in_path, out_path))
def deploy(remote='origin'):
"""
Deploy the latest app.
"""
render()
_deploy_to_file_server()
"""
Destruction
Changes to destruction require setup/deploy to a test host in order to test.
Destruction should remove all files related to the project from both a remote
host and S3.
"""
def _confirm(message):
answer = prompt(message, default="Not at all")
if answer.lower() not in ('y', 'yes', 'buzz off', 'screw you'):
exit()
def shiva_the_destroyer():
"""
Deletes the app from s3
"""
# TODO: not updated for file_server
pass