~ya-bo-ng/juju-gui/test-prototype

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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
# Makefile debugging hack: uncomment the two lines below and make will tell you
# more about what is happening.  The output generated is of the form
# "FILE:LINE [TARGET (DEPENDENCIES) (NEWER)]" where DEPENDENCIES are all the
# things TARGET depends on and NEWER are all the files that are newer than
# TARGET.  DEPENDENCIES will be colored green and NEWER will be blue.
#
#OLD_SHELL := $(SHELL)
#SHELL = $(warning [$@ ($^) ($?) ])$(OLD_SHELL)

# Build a target for JavaScript files.  The find command excludes directories
# as needed through the -prune directive, and the grep command removes
# individual unwanted JavaScript and JSON files from the list.
# find(1) is used here to build a list of JavaScript targets rather than bzr
# due to the speed of network access being unpredictable (bzr accesses the
# parent branch, which may be lp:juju-gui, for any command relating to the
# branch or checkout).  Additionally, working with the release or an export,
# a developer may not be working in a bzr repository.
JSFILES=$(shell find . -wholename './node_modules*' -prune \
	-o -wholename './build*' -prune \
	-o -wholename './.bzr*' -prune \
	-o -wholename './docs*' -prune \
	-o -wholename './test/assets*' -prune \
	-o -wholename './yuidoc*' -prune \
	-o \( \
		-name '*.js' \
		-o -name '*.json' \
		-o -name 'generateTemplates' \
	\) -print \
	| sort | sed -e 's/^\.\///' \
	| grep -Ev -e '^manifest\.json$$' \
		-e '^app/assets/javascripts/d3(\.min)?\.js$$' \
		-e '^app/assets/javascripts/spin\.min\.js$$' \
		-e '^app/assets/javascripts/spinner\.js$$' \
		-e '^app/assets/javascripts/js-yaml\.min\.js$$' \
		-e '^app/assets/javascripts/reconnecting-websocket\.js$$' \
		-e '^app/assets/javascripts/prettify.js$$' \
		-e '^app/assets/javascripts/FileSaver.js$$' \
		-e '^app/assets/javascripts/gallery-.*\.js$$' \
		-e '^server.js$$')
THIRD_PARTY_JS=app/assets/javascripts/reconnecting-websocket.js
LINT_IGNORE='app/assets/javascripts/prettify.js, app/assets/javascripts/FileSaver.js, app/assets/javascripts/spinner.js, app/assets/javascripts/Object.observe.poly.js'
NODE_TARGETS=node_modules/chai node_modules/cryptojs node_modules/d3 \
    node_modules/expect.js node_modules/express \
    node_modules/graceful-fs node_modules/grunt node_modules/jshint \
    node_modules/less node_modules/minimatch node_modules/mocha \
    node_modules/node-markdown node_modules/node-minify \
    node_modules/node-spritesheet node_modules/recess \
    node_modules/rimraf node_modules/should node_modules/uglify-js \
    node_modules/yui node_modules/yuidocjs
EXPECTED_NODE_TARGETS=$(shell echo "$(NODE_TARGETS)" | tr ' ' '\n' | sort \
	| tr '\n' ' ')

### Release-specific variables - see docs/process.rst for an overview. ###
# Provide the ability to build a release package without using bzr, for
# lightweight checkouts.
ifdef NO_BZR
BZR_REVNO=0
BRANCH_IS_GOOD=1
else
BZR_REVNO=$(shell bzr revno)
endif
# Figure out the two most recent version numbers.
ULTIMATE_VERSION=$(shell grep '^-' CHANGES.yaml | head -n 1 | sed 's/[ :-]//g')
PENULTIMATE_VERSION=$(shell grep '^-' CHANGES.yaml | head -n 2 | tail -n 1 \
    | sed 's/[ :-]//g')
RELEASE_TARGETS=dist
# If the user specified (via setting an environment variable on the command
# line) that this is a final (non-development) release, set the version number
# and series appropriately.
ifdef FINAL
# If this is a FINAL (non-development) release, then the most recent version
# number should not be "unreleased".
ifneq (, $(filter $(RELEASE_TARGETS), $(MAKECMDGOALS)))
ifeq ($(ULTIMATE_VERSION), unreleased)
    $(error FINAL releases must have a most-recent version number other than \
	"unreleased" in CHANGES.yaml)
endif
endif
RELEASE_VERSION=$(ULTIMATE_VERSION)
SERIES=stable
else
# If this is development (non-FINAL) release, then the most recent version
# number must be "unreleased".
ifneq (, $(filter $(RELEASE_TARGETS), $(MAKECMDGOALS)))
ifneq ($(ULTIMATE_VERSION), unreleased)
    $(error non-FINAL releases must have a most-recent version number of \
	"unreleased" in CHANGES.yaml)
endif
endif
RELEASE_VERSION=$(PENULTIMATE_VERSION)+build.$(BZR_REVNO)
SERIES=trunk
endif
# If we are doing a production release (as opposed to a trial-run release) we
# use the "real" Launchpad site, if not we use the Launchpad staging site.
ifndef PROD
LAUNCHPAD_API_ROOT=staging
endif
RELEASE_NAME=juju-gui-$(RELEASE_VERSION)
RELEASE_FILE=releases/$(RELEASE_NAME).tgz
RELEASE_SIGNATURE=releases/$(RELEASE_NAME).asc
NPM_CACHE_VERSION=$(BZR_REVNO)
NPM_CACHE_FILE=$(CURDIR)/releases/npm-cache-$(NPM_CACHE_VERSION).tgz
NPM_SIGNATURE=$(NPM_CACHE_FILE).asc
# Is the branch being released a branch of trunk?
ifndef BRANCH_IS_GOOD
ifndef IS_TRUNK_BRANCH
IS_TRUNK_BRANCH=$(shell bzr info | grep \
	'parent branch: bzr+ssh://bazaar.launchpad.net/+branch/juju-gui/' \
	> /dev/null && echo 1)
endif
# Does the branch on disk have uncomitted/unpushed changes?
ifndef BRANCH_IS_CLEAN
BRANCH_IS_CLEAN=$(shell [ -z "`bzr status`" ] && bzr missing --this && echo 1)
endif
# Is it safe to do a release of the branch?  For trial-run releases you can
# override this check on the command line by setting the BRANCH_IS_GOOD
# environment variable.
ifneq ($(strip $(IS_TRUNK_BRANCH)),)
ifneq ($(strip $(BRANCH_IS_CLEAN)),)
BRANCH_IS_GOOD=1
endif
endif
endif
### End of release-specific variables ###
TEMPLATE_TARGETS=$(shell find app -type f -regextype posix-extended -regex '.+\.(handlebars|partial)')

CSS_TARGETS=$(shell find lib/views -type f -name '*.less') \
    $(shell find app/assets/css -type f -name '*.scss')

SPRITE_SOURCE_FILES=$(shell find app/assets/images -type f ! -name '.*' ! -name '*.swp' ! -name '*~' ! -name '\#*' -print)
SPRITE_GENERATED_FILES=build-shared/juju-ui/assets/sprites.css \
	build-shared/juju-ui/assets/sprites.png
NON_SPRITE_IMAGES=build-shared/juju-ui/assets/images
BUILD_FILES=build-shared/juju-ui/assets/modules.js \
	build-shared/juju-ui/assets/all-yui.js \
	build-shared/juju-ui/assets/combined-css/all-static.css
JAVASCRIPT_LIBRARIES=app/assets/javascripts/d3.js \
	app/assets/javascripts/d3.min.js app/assets/javascripts/yui
DATE=$(shell date -u)

# Some environments, notably sudo, do not populate the default PWD environment
# variable, which is used to set $(PWD).  Worse, in some situations, such as
# using make -C [directory], $(PWD) is set to a value we don't want: the
# directory in which make was invoked, rather than the directory of this file.
# Therefore, we want to run the shell's pwd to get this Makefile's directory.
# As an optimization, we stash this value in the local PWD variable.
PWD=$(shell pwd)

all: build virtualenv/bin/python
	@echo "\nDebug and production environments built."
	@echo "Run 'make help' to list the main available targets."

help:
	@echo "Main targets:"
	@echo "[no target] or build: build the debug and production environments"
	@echo "devel: run the development environment (dynamic templates/CSS)"
	@echo "debug: run the debugging environment (static templates/CSS)"
	@echo "prod: run the production environment (aggregated, compressed files)"
	@echo "clean: remove the generated build directories"
	@echo "clean-all: remove build, deps and doc directories"
	@echo "test-debug: run tests on the cli from the debug environment"
	@echo "test-prod: run tests on the cli from the production environment"
	@echo "test-misc: run tests of project infrastructure bits"
	@echo "test-server: run tests in the browser from the debug environment"
	@echo "test-prod-server: run tests in the browser from the prod environment"
	@echo "prep: beautify and lint the source"
	@echo "docs: generate project and code documentation"
	@echo "check: run checks used by lbox"
	@echo "view-docs: generate both doc sets and view them in the browser"
	@echo "help: this description"
	@echo "Other targets are available.  See the Makefile."

build-shared/juju-ui/templates.js: $(TEMPLATE_TARGETS) bin/generateTemplates
	mkdir -p build-shared/juju-ui/assets
	bin/generateTemplates

yuidoc/index.html: node_modules/yuidocjs $(JSFILES)
	node_modules/.bin/yuidoc --lint -o yuidoc -x assets app

main-doc:
	make -C docs SPHINXOPTS=-W html

view-main-doc: main-doc
	xdg-open docs/_build/html/index.html

sphinx:
	@echo "Deprecated. Please run 'make main-doc' or 'make view-main-doc'."

code-doc: yuidoc/index.html

view-code-doc: code-doc
	xdg-open yuidoc/index.html

yuidoc:
	@echo "Deprecated. Please run 'make code-doc' or 'make view-code-doc'."

docs: code-doc main-doc

view-docs: docs
	xdg-open docs/_build/html/index.html
	xdg-open yuidoc/index.html

$(SPRITE_GENERATED_FILES): node_modules/grunt node_modules/node-spritesheet \
		$(SPRITE_SOURCE_FILES)
	node_modules/grunt/bin/grunt spritegen

$(NON_SPRITE_IMAGES):
	mkdir -p build-shared/juju-ui/assets/images
	cp -r app/assets/images/non-sprites/* build-shared/juju-ui/assets/images/

install-npm-packages: $(NODE_TARGETS)

$(NODE_TARGETS): package.json
	npm install --cache-min=999999999
	# Keep all targets up to date, not just new/changed ones.
	for dirname in $(NODE_TARGETS); do touch $$dirname ; done
	@# Check to see if we made what we expected to make, and warn if we did
	@# not. Note that we calculate FOUND_TARGETS here, in this way and not
	@# in the standard Makefile way, because we need to see what
	@# node_modules were created by this target.  Makefile variables and
	@# substitutions, even when using $(eval...) within a target, happen
	@# initially, before the target is run.	 Therefore, if this were a
	@# simple Makefile variable, it	would be empty after a first run, and
	@# you would always see the warning message in that case.  We have to
	@# connect it to the "if" command with "; \\" because Makefile targets
	@# are evaluated per line, with bash variables discarded between them.
	@# We compare the result with EXPECTED_NODE_TARGETS and not simply the
	@# NODE_TARGETS because this gives us normalization, particularly of the
	@# trailing whitespace, that we do not otherwise have.
	@FOUND_TARGETS=$$(find node_modules -maxdepth 1 -mindepth 1 -type d \
	-printf 'node_modules/%f ' | tr ' ' '\n' | grep -Ev '\.bin$$' \
	| sort | tr '\n' ' '); \
	if [ "$$FOUND_TARGETS" != "$(EXPECTED_NODE_TARGETS)" ]; then \
	echo; \
	echo "******************************************************************"; \
	echo "******************************************************************"; \
	echo "******************************************************************"; \
	echo "******************************************************************"; \
	echo "IMPORTANT: THE NODE_TARGETS VARIABLE IN THE MAKEFILE SHOULD CHANGE"; \
	echo "******************************************************************"; \
	echo "******************************************************************"; \
	echo "******************************************************************"; \
	echo "******************************************************************"; \
	echo; \
	echo "Change it to the following."; \
	echo; \
	echo $$FOUND_TARGETS; \
	fi

$(JAVASCRIPT_LIBRARIES): | node_modules/yui node_modules/d3
	ln -sf "$(PWD)/node_modules/yui" app/assets/javascripts/yui
	ln -sf "$(PWD)/node_modules/d3/d3.js" app/assets/javascripts/d3.js
	ln -sf "$(PWD)/node_modules/d3/d3.min.js" \
		app/assets/javascripts/d3.min.js

gjslint: virtualenv/bin/gjslint
	virtualenv/bin/gjslint --unix --strict --nojsdoc --jslint_error=all \
	    --custom_jsdoc_tags module,main,class,method,event,property,attribute,submodule,namespace,extends,config,constructor,static,final,readOnly,writeOnce,optional,required,param,return,for,type,private,protected,requires,default,uses,example,chainable,deprecated,since,async,beta,bubbles,extension,extensionfor,extension_for \
		-x $(LINT_IGNORE) $(JSFILES) \
	    | sed -n '0,/^Found /p'| sed '/^Found /q1' # less garbage output

jshint: node_modules/jshint
	node_modules/jshint/bin/hint $(JSFILES)

undocumented:
	bin/lint-yuidoc --generate-undocumented > undocumented

lint-yuidoc: $(JSFILES)
	node_modules/.bin/yuidoc --lint -x assets app
	bin/lint-yuidoc

recess: node_modules/recess
	@# We need to grep for "Perfect" because recess does not set a
	@# non-zero exit code if it rejects a file.  If this fails, run the
	@# recess command below without the grep to get recess' report.
	node_modules/recess/bin/recess lib/views/stylesheet.less \
	    --config recess.json | grep -q Perfect

lint: test-prep jshint gjslint recess lint-license-headers test-filtering \
		lint-yuidoc

lint-license-headers:
	@# Take the list of JS files in one long line and break them into
	@# multiple lines (this assumes there are no spaces in the paths).
	@# Remove non-JS files, remove third-party files, and remove files in
	@# the root of the project.  Finally, search for copyright notices in
	@# the files and report files that do not have one.
	echo $(JSFILES) | sed 's/ /\n/g' \
	| grep '\.js$$' | grep -v /assets/ | grep / \
	| xargs -I {} sh -c "grep -L '^Copyright (C) 2[^ ]* Canonical Ltd.' {}" \
	|| (echo "The above files are missing copyright headers."; false)

virtualenv/bin/python:
	virtualenv virtualenv --system-site-packages
	virtualenv/bin/easy_install archives/selenium-2.33.0.tar.gz

virtualenv/bin/gjslint virtualenv/bin/fixjsstyle: virtualenv/bin/python
	virtualenv/bin/easy_install archives/closure_linter-latest.tar.gz

beautify: virtualenv/bin/fixjsstyle
	virtualenv/bin/fixjsstyle --strict --nojsdoc --jslint_error=all $(JSFILES)

spritegen: $(SPRITE_GENERATED_FILES)

$(BUILD_FILES): $(JSFILES) $(CSS_TARGETS) $(THIRD_PARTY_JS) \
		build-shared/juju-ui/templates.js \
		bin/merge-files lib/merge-files.js \
		app/assets/javascripts/js-yaml.min.js \
		app/assets/javascripts/spin.min.js | $(JAVASCRIPT_LIBRARIES)
	rm -f $(BUILD_FILES)
	mkdir -p build-shared/juju-ui/assets/combined-css/
	ln -sf \
	    "$(PWD)/node_modules/yui/slider-base/assets/skins/sam/rail-x.png" \
	    build-shared/juju-ui/assets/combined-css/rail-x.png
	ln -sf \
	    "$(PWD)/node_modules/yui/slider-base/assets/skins/sam/rail-y.png" \
	    build-shared/juju-ui/assets/combined-css/rail-y.png
	ln -sf \
	    "$(PWD)/node_modules/yui/slider-base/assets/skins/sam/thumb-x.png" \
	    build-shared/juju-ui/assets/combined-css/thumb-x.png
	ln -sf \
	    "$(PWD)/node_modules/yui/slider-base/assets/skins/sam/thumb-y.png" \
	    build-shared/juju-ui/assets/combined-css/thumb-y.png
	bin/merge-files
	mv *.js.map build-shared/juju-ui/assets/

build-files: $(BUILD_FILES)

# This leaves out all of the individual YUI assets, because we can't have them
# the first time the Makefile is run in a clean tree.
shared-link-files-list=build-$(1)/juju-ui/assets/combined-css \
	build-$(1)/favicon.ico \
	build-$(1)/index.html \
	build-$(1)/juju-ui/assets/config.js \
	build-$(1)/juju-ui/assets/modules.js \
	build-$(1)/juju-ui/assets/images \
	build-$(1)/juju-ui/assets/svgs \
	build-$(1)/juju-ui/version.js \
	build-$(1)/juju-ui/assets/combined-css/all-static.css \
	build-$(1)/juju-ui/assets/juju-gui.css \
	build-$(1)/juju-ui/assets/sprites.css \
	build-$(1)/juju-ui/assets/sprites.png \
	build-$(1)/juju-ui/assets/combined-css/rail-x.png \
	build-$(1)/juju-ui/assets/combined-css/rail-y.png \
	build-$(1)/juju-ui/assets/combined-css/thumb-x.png \
	build-$(1)/juju-ui/assets/combined-css/thumb-y.png \
	build-$(1)/juju-ui/assets/all-yui.js

LINK_DEBUG_FILES=$(call shared-link-files-list,debug) \
	build-debug/juju-ui/app.js \
	build-debug/juju-ui/websocket-logging.js \
	build-debug/juju-ui/models \
	build-debug/juju-ui/store \
	build-debug/juju-ui/subapps \
	build-debug/juju-ui/views \
	build-debug/juju-ui/widgets \
	build-debug/juju-ui/assets/javascripts \
	build-debug/juju-ui/templates.js

LINK_PROD_FILES=$(call shared-link-files-list,prod)

# These are shared instructions between link-debug-files and link-prod-files.
define link-files
	mkdir -p build-$(1)/juju-ui/assets/combined-css
	ln -sf "$(PWD)/app/favicon.ico" build-$(1)/
	ln -sf "$(PWD)/app/index.html" build-$(1)/
	ln -sf "$(PWD)/app/config-$(1).js" build-$(1)/juju-ui/assets/config.js
	ln -sf "$(PWD)/app/assets/images" build-$(1)/juju-ui/assets/
	ln -sf "$(PWD)/app/assets/svgs" build-$(1)/juju-ui/assets/
	ln -sf "$(PWD)/app/assets/javascripts" build-$(1)/juju-ui/assets/
	ln -sf "$(PWD)/build-shared/juju-ui/version.js" build-$(1)/juju-ui/
	ln -sf \
	    "$(PWD)/build-shared/juju-ui/assets/combined-css/all-static.css" \
	    build-$(1)/juju-ui/assets/combined-css/
	ln -sf \
	    "$(PWD)/build-shared/juju-ui/assets/combined-css/rail-x.png" \
	    build-$(1)/juju-ui/assets/combined-css/
	ln -sf \
	    "$(PWD)/build-shared/juju-ui/assets/combined-css/rail-y.png" \
	    build-$(1)/juju-ui/assets/combined-css/
	ln -sf \
	    "$(PWD)/build-shared/juju-ui/assets/combined-css/thumb-x.png" \
	    build-$(1)/juju-ui/assets/combined-css/
	ln -sf "$(PWD)/build-shared/juju-ui/assets/combined-css/thumb-y.png" \
	    build-$(1)/juju-ui/assets/combined-css/
	ln -sf "$(PWD)/build-shared/juju-ui/assets/juju-gui.css" \
	    build-$(1)/juju-ui/assets/
	ln -sf "$(PWD)/build-shared/juju-ui/assets/sprites.css" \
	    build-$(1)/juju-ui/assets/
	ln -sf "$(PWD)/build-shared/juju-ui/assets/sprites.png" \
	    build-$(1)/juju-ui/assets/
	ln -sf "$(PWD)/node_modules/yui/event-simulate/event-simulate.js" \
	    build-$(1)/juju-ui/assets/
	ln -sf \
	    "$(PWD)/node_modules/yui/node-event-simulate/node-event-simulate.js" \
	    build-$(1)/juju-ui/assets
	# Copy each YUI module's assets to a parallel directory in the build
	# location.  This is run in a subshell (indicated by the parenthesis)
	# so we can change directory and have it not effect this process.  To
	# understand how it does what it does look at the man page for cp,
	# particularly "--parents".  Notice that this makes copies instead of
	# links.  This goes against the way the dependencies are structured and
	# so may be a problem in the future.  If so, a way to do this as links
	# would be called for.
	(cd node_modules/yui/ && \
	 cp -r --parents */assets "$(PWD)/build-$(1)/juju-ui/assets/")
endef

$(LINK_DEBUG_FILES):
	$(call link-files,debug)
	ln -sf "$(PWD)/app/app.js" build-debug/juju-ui/
	ln -sf "$(PWD)/app/websocket-logging.js" build-debug/juju-ui/
	ln -sf "$(PWD)/app/models" build-debug/juju-ui/
	ln -sf "$(PWD)/app/store" build-debug/juju-ui/
	ln -sf "$(PWD)/app/subapps" build-debug/juju-ui/
	ln -sf "$(PWD)/app/views" build-debug/juju-ui/
	ln -sf "$(PWD)/app/widgets" build-debug/juju-ui/
	ln -sf "$(PWD)/app/assets/javascripts/yui/yui/yui-debug.js" \
		build-debug/juju-ui/assets/all-yui.js
	ln -sf "$(PWD)/build-shared/juju-ui/templates.js" build-debug/juju-ui/
	ln -sf "$(PWD)/app/modules-debug.js" build-debug/juju-ui/assets/modules.js

$(LINK_PROD_FILES):
	$(call link-files,prod)
	ln -sf "$(PWD)/build-shared/juju-ui/assets/all-yui.js" build-prod/juju-ui/assets/
	ln -sf "$(PWD)"/build-shared/juju-ui/assets/*.js.map build-prod/juju-ui/assets/
	# Link in the application source code so source maps work.
	mkdir -p $(PWD)/build-prod/juju-ui/assets/source
	ln -s $(PWD)/app $(PWD)/build-prod/juju-ui/assets/source
	ln -s $(PWD)/node_modules $(PWD)/build-prod/juju-ui/assets/source
	ln -sf "$(PWD)/build-shared/juju-ui/assets/modules.js" build-prod/juju-ui/assets/modules.js

prep: beautify lint

check: lint test-prod test-debug test-misc docs

test/extracted_startup_code: app/index.html
	# Pull the JS out of the index so we can run tests against it.
	cat app/index.html | \
	    sed -n '/<script id="app-startup">/,/<\/script>/p'| \
	    head -n-1 | tail -n+2 > test/extracted_startup_code

test/test_startup.js: test/test_startup.js.top test/test_startup.js.bottom \
    test/extracted_startup_code
	# Stitch together the test file for app start-up.
	echo "// THIS IS A GENERATED FILE.  DO NOT EDIT." > $@
	echo "// See the Makefile for details." >> $@
	cat test/test_startup.js.top >> $@
	cat test/extracted_startup_code >> $@
	cat test/test_startup.js.bottom >> $@

test-prep: test/test_startup.js

test-filtering:
	./bin/test-filtering

test-debug: build-debug test-prep
	./test-server.sh debug

test-prod: build-prod test-prep
	./test-server.sh prod

test-server: build-debug test-prep
	./test-server.sh debug true

test-prod-server: build-prod test-prep
	./test-server.sh prod true

test-misc:
	PYTHONPATH=lib python test/test_websocketreplay.py
	PYTHONPATH=lib python test/test_deploy_charm_for_testing.py
	PYTHONPATH=bin python test/test_http_server.py

test:
	@echo "Deprecated. Please run either 'make test-prod' or 'make"
	@echo "test-debug', to test the production or debug environments"
	@echo "respectively.  Run 'make help' to list the main available "
	@echo "targets."

server:
	@echo "Deprecated. Please run either 'make prod' or 'make debug',"
	@echo "to start the production or debug environments respectively."
	@echo "Run 'make help' to list the main available targets."

# devel is used during the development process.
devel: build-devel
	@echo "Running the development environment from node.js ."
	@echo "Customize config.js to modify server settings."
	node server.js

# debug is for deployments of unaggregated and uncompressed code.
debug: build-debug
	@echo "Running the debug environment from a SimpleHTTPServer"
	@echo "To run the development environment, including automatically"
	@echo "rebuilding the generated files on changes, run 'make devel'."
	(cd build-debug && python ../bin/http_server.py 8888)

# prod is for deployment of aggregated and minimized code.
prod: build-prod
	@echo "Running the production environment from a SimpleHTTPServer"
	(cd build-prod && python ../bin/http_server.py 8888)

clean:
	rm -rf build-shared build-debug build-prod
	find app/assets/javascripts/ -type l | xargs rm -rf
	rm -f test/test_startup.js

clean-deps:
	rm -rf node_modules virtualenv

clean-docs:
	make -C docs clean
	rm -rf yuidoc

clean-all: clean clean-deps clean-docs

build: build-prod build-debug build-devel

build-shared: build-shared/juju-ui/assets $(NODE_TARGETS) spritegen \
	  $(NON_SPRITE_IMAGES) $(BUILD_FILES) build-shared/juju-ui/version.js

# build-devel is phony. build-shared, build-debug, and build-common are real.
build-devel: build-shared

build-debug: build-shared | $(LINK_DEBUG_FILES)

build-prod: build-shared | $(LINK_PROD_FILES)

build-shared/juju-ui/assets:
	mkdir -p build-shared/juju-ui/assets

# This really depends on CHANGES.yaml, the bzr revno changing, and the build
# /juju-ui directory existing.  We are vaguely trying to approximate the second
# one by connecting it to our pertinent versioned files.  The first target
# creates the directory, and directories are a bit tricky with Makefiles so we
# are OK with that.  The ULTIMATE_VERSION is used here because we always want
# the version.js file to reflect the top-most entry in the CHANGES.yaml file,
# regardless of whether we are doing a "Stable" or "Development" release.
build-shared/juju-ui/version.js: build-shared/juju-ui/assets CHANGES.yaml $(JSFILES) $(TEMPLATE_TARGETS) \
		$(SPRITE_SOURCE_FILES)
	echo "var jujuGuiVersionInfo=['$(ULTIMATE_VERSION)', '$(BZR_REVNO)'];" \
	    > build-shared/juju-ui/version.js

upload_release.py:
	bzr cat lp:launchpadlib/contrib/upload_release_tarball.py \
	    > upload_release.py

$(RELEASE_FILE): build test-prep
	@echo "$(BRANCH_IS_CLEAN)"
ifdef BRANCH_IS_GOOD
	mkdir -p releases
	# When creating the tarball, ensure all symbolic links are followed.
	tar -c --auto-compress --exclude-vcs --exclude releases \
	    --dereference --transform "s|^|$(RELEASE_NAME)/|" -f $(RELEASE_FILE) *
	@echo "Release was created in $(RELEASE_FILE)."
else
	@echo "**************************************************************"
	@echo "*********************** RELEASE FAILED ***********************"
	@echo "**************************************************************"
	@echo
	@echo "To make a release, you must either be in a branch of"
	@echo "lp:juju-gui without uncommitted/unpushed changes, or you must"
	@echo "override one of the pertinent variable names to force a "
	@echo "release."
	@echo
	@echo "See the README for more information."
	@echo
	@false
endif

distfile: $(RELEASE_FILE)

$(RELEASE_SIGNATURE): $(RELEASE_FILE)
	gpg --armor --sign --detach-sig $(RELEASE_FILE)

dist: $(RELEASE_FILE) $(RELEASE_SIGNATURE) upload_release.py
ifndef NO_BZR
	python2 upload_release.py juju-gui $(SERIES) $(RELEASE_VERSION) \
	    $(RELEASE_FILE) $(LAUNCHPAD_API_ROOT)
else
	@echo "**************************************************************"
	@echo "*********************** DIST FAILED **************************"
	@echo "**************************************************************"
	@echo
	@echo "You may not make dist while the NO_BZR flag is defined."
	@echo "Please run this target without the NO_BZR flag defined if you"
	@echo "wish to upload a release."
	@echo
	@echo "See docs/process.rst for more information"
	@echo
	@false
endif

$(NPM_SIGNATURE): $(NPM_CACHE_FILE)
	gpg --armor --sign --detach-sig $(NPM_CACHE_FILE)

npm-cache-file: $(NPM_CACHE_FILE)

$(NPM_CACHE_FILE):
	# We store the NPM cache file in the "releases" directory.  It is kind
	# of like a release.
	mkdir -p releases
	# Remove any old cache or generated cache archives.
	rm -f releases/npm-cache-*.tgz*
	rm -rf temp-npm-cache
	# We have to get rid of all installed NPM packages so they will be
	# reinstalled into the (presently) empty cache.
	$(MAKE) clean-all
	# Install all the NPM packages, overriding the NPM cache.
	$(MAKE) npm_config_cache=temp-npm-cache install-npm-packages
	(cd temp-npm-cache && tar czvf $(NPM_CACHE_FILE) .)
	rm -rf temp-npm-cache

npm-cache: $(NPM_CACHE_FILE) $(NPM_SIGNATURE)
ifdef BRANCH_IS_GOOD
	python2 upload_release.py juju-gui npm-cache $(NPM_CACHE_VERSION) \
	    $(NPM_CACHE_FILE) $(LAUNCHPAD_API_ROOT)
else
	@echo "**************************************************************"
	@echo "**************** NPM CACHE GENERATION FAILED *****************"
	@echo "**************************************************************"
	@echo
	@echo "To create and upload an NPM cache file to Launchpad you must"
	@echo "be in a branch of lp:juju-gui without uncommitted/unpushed"
	@echo "changes, or you must override one of the pertinent variable "
	@echo "names to force an upload."
	@echo
	@echo "See docs/process.rst for more information"
	@echo
	@false
endif

# targets are alphabetically sorted, they like it that way :-)
.PHONY: beautify build build-files build-devel clean clean-all clean-deps \
	clean-docs code-doc debug devel docs dist gjslint help \
	install-npm-packages jshint lint lint-yuidoc main-doc npm-cache \
	npm-cache-file prep prod recess server spritegen test test-debug \
	test-misc test-prep test-prod undocumented view-code-doc view-docs \
	view-main-doc

.DEFAULT_GOAL := all