-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
1640 lines (1368 loc) · 75.1 KB
/
index.html
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
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en-US" prefix="og: http://opg.me/ns#">
<head>
<meta charset="UTF-8" />
<meta prefix="og: http://ogp.me/ns#" name="title" property="og:title" content="Stagehand" />
<meta prefix="og: http://ogp.me/ns#" name="description" property="og:description"
content="Stagehand makes getting to production for frontend teams as painless as possible. We are a drop in solution for automating review apps for your frontend application." />
<meta prefix="og: http://ogp.me/ns#" name="type" property="og:type" content="website" />
<meta prefix="og: http://ogp.me/ns#" name="url" property="og:url" content="https://stagehand-framework.github.io/" />
<meta prefix="og: http://ogp.me/ns#" name="image" property="og:image"
content="images/logos/stagehand_logo-full.png" />
<meta prefix="og: http://ogp.me/ns#" name="viewport" content="width=device-width, initial-scale=1" />
<meta prefix="og: http://ogp.me/ns#" name="author" content="Cody Stair, Daniel Lew, Emil Reji" />
<title>Stagehand</title>
<link rel="apple-touch-icon" sizes="180x180" href="/images/icons/favicons/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/images/icons/favicons/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/images/icons/favicons/favicon-16x16.png" />
<link rel="manifest" href="/images/icons/favicons/site.webmanifest" />
<link rel="mask-icon" href="/images/icons/favicons/safari-pinned-tab.svg" color="#5bbad5" />
<link rel="shortcut icon" href="/images/icons/favicons/favicon.ico" />
<meta name="msapplication-TileColor" content="#da532c" />
<meta name="msapplication-config" content="/images/icons/favicons/browserconfig.xml" />
<meta name="theme-color" content="#ffffff" />
<!-- <style>reset</style> -->
<link rel="stylesheet" href="stylesheets/reset.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/gruvbox-dark.min.css"
charset="utf-8" />
<!-- <style></style> -->
<link rel="stylesheet" href="stylesheets/main.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
<!-- slick carousel style -->
<link rel="stylesheet" type="text/css" href="slick/slick.css" />
<link rel="stylesheet" type="text/css" href="slick/slick-theme.css" />
<!-- <script></script> -->
<script src="javascripts/application.js"></script>
<style></style>
</head>
<body>
<img id="stagehand-logo" src="images/logos/stagehand_logo-mark.png" />
<div class="logo-links">
<a href="https://github.com/stagehand-framework" target="_blank">
<img src="images/logos/stagehand_github-black.png" alt="github logo" id="github-logo" />
</a>
</div>
<a id="toTop-link" href="#" target="_blank">
<img src="images/logos/back-to-top.png" alt="Back to top" id="toTop-logo" />
</a>
<nav id="site-navigation">
<ul>
<li>
<a href="#home" id="home-link">HOME</a>
</li>
<li>
<a href="#case-study" id="case-study-link">CASE STUDY</a>
<nav id="case-study-mobile">
<ul></ul>
</nav>
</li>
<li>
<a href="#our-team" id="our-team-link">OUR TEAM</a>
</li>
</ul>
</nav>
<header id="home">
<h1>
<img src="images/logos/stagehand_logo-full.png" alt="Stagehand logo" />
<p>Automated review apps for modern frontend applications</p>
</h1>
</header>
<section class="integration">
<div class="box">
<img id="banner-deploy" src="images/diagrams/High-level-SH.png"
alt="A simplified diagram of Stagehand's infrastructure" />
</div>
<article class="box">
<div class="text-box">
<h1>
Stagehand allows you to deploy and manage your review apps on your
own infrastructure.
</h1>
</div>
</article>
</section>
<section class="integration">
<article class="box">
<div class="text-box">
<h1>
Stagehand automates review apps for you. All you need is a GitHub account
and an AWS account.
</h1>
</div>
</article>
<div class="box">
<img id="banner-deploy" src="images/diagrams/GH-AWS-logo.png" alt="Stagehand's logo" />
</div>
</section>
<main>
<section id="case-study">
<h1>Case Study</h1>
<div id="side-nav">
<img src="images/logos/stagehand_logo-full.png" alt="Stagehand logo" />
</div>
<nav>
<ul></ul>
</nav>
<h2 id="what-is-stagehand">1. What is Stagehand?</h2>
<p>
Stagehand is a drop-in solution that provides review apps for modern
frontend applications. Using AWS, GitHub Actions, and some Stagehand
client-side code we set-up, deploy, manage, and teardown review apps
for your frontend application. All the code and infrastructure lives on your own accounts so you're in total control.
</p>
<div class="img-wrapper">
<img src="images/diagrams/steps.png" alt="steps to get Stagehand working" />
</div>
<p>
All you have to do is install the Stagehand CLI via our NPM package
and run <code>stagehand init</code> in your local repo. Once your code is pushed to a GitHub repository, you will have
review apps automatically deployed for you to view and share whenever
you open a pull request or make any additional commits on that pull
request. We automate all the hard parts for you, so you can focus on developing your application code.
</p>
<p>
Here's an example of what it looks like when you're all set up:
</p>
<div class="video-container">
<iframe width="560" height="315" src="images/diagrams/stagehand-demo.mp4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen class="video"></iframe>
</div>
<p>
The video starts with a pull request opening, triggering a review app to be created. A commit is then made off-screen with a "New Change", creating another review app. Every review app has our basic Stagehand dashboard which opens up by hovering over the banner at the top.
</p>
<p>
The code for the dashboard is inserted into your GitHub repository in the <code>stagehand.html</code> file so feel free to change it and customize it to fit your own needs!
</p>
<p>
Over the course of this case study, we're going to go through the problems we solve for developers and then we'll dive into how we built Stagehand and the challenges that came along with it.
</p>
<h2 id="what-are-review-apps">2. What are Review Apps?</h2>
<p>
In this section we will dive into review apps and the value they bring to frontend developers.
</p>
<h3>2.1. Staging Environments</h3>
<p>
To see where review apps fit into the overall continuous development
of a production application, let’s consider the various environments
involved in that application.
</p>
<div class="img-wrapper">
<img src="images/diagrams/environments.png" alt="environments diagram" />
</div>
<p>
The first environment we touch, development, is where we make code changes to our application. This involves a developer coding a feature and testing
it out on their local machine.
</p>
<p>
Once we're satisfied with how that feature works locally, we can move it on to a dedicated testing environment. This environment is
optimized for whatever aspects of the application are being tested
(specific units, end-to-end functionality, etc.).
</p>
<p>
Prior to deploying live, the new feature code is moved to a staging
environment. This environment is supposed to match the production
environment as closely as possibly for any final checks. [<a href="#footnote-1">1</a>] Finally, the new code
moves to the production environment to go
live.
</p>
<blockquote>
“A staging environment (sometimes called a pre-production environment)
is the environment where your code is ‘staged’ prior to being run in
front of users so you can ensure it works as designed.” [<a href="#footnote-2">2</a>]
</blockquote>
<p>
A staging environment can be used for quality assurance teams,
automated end-to-end testing, and for product managers and/or other
stakeholders to be able to validate that new features and
functionality work as intended.
</p>
<p>
Review apps generally fall under the same category as staging
environments, though their usefulness may expand beyond that.
</p>
<h3>2.2. Using a Staging Environment</h3>
<p>
Consider this scenario where you are a developer of a frontend
application:
</p>
<div class="img-wrapper">
<img src="images/diagrams/scenario_1.png" alt="single developer w/ staging environment" />
</div>
<p>
The product manager wants a responsive navigation bar added to the
application. After coding up and
testing your new navigation bar feature, you deploy your changes to a
staging environment.
</p>
<p>
In this staging environment, the product manager and other
stakeholders can view your changes in a production-like environment.
They can play around with the new functionality, making sure it is
what they want and that everything works properly. Then, once your new
feature is approved, it can be moved into production to be released.
</p>
<p>
Now you, Alice, and Bob are all working on multiple features of the frontend application at the same time. You are
working on the navigation bar feature, Alice is working on the footer,
and Bob is working on the page content:
</p>
<div class="img-wrapper">
<img src="images/diagrams/scenario_2.png" alt="multiple developers w/ shared staging environment" />
</div>
<p>
All of these features will have to be deployed to a shared staging
environment. The new features are verified by the
product manager and other stakeholders before being approved to go
into production.
</p>
<p>
Sharing this environment means maybe you and Alice have to
wait until Bob is done using it before you can deploy and share your
new features. Or even, you or Alice may have to clean up the
staging environment if Bob made changes to it. And if your code now
conflicts with Bob’s, you may have to resolve these conflicts.
</p>
<p>
This type of bottleneck in the development cycle is far too common and can be remedied by having review apps.
</p>
<h3>2.3. Review Apps</h3>
<p>
Review apps are ephemeral, fully-functional versions of a production
application that can be easily deployed and shared with others[<a href="#footnote-3">3</a>].
</p>
<ul>
<li>
Ephemeral - <em>temporary environments</em> that can be built
and torn down at any time
</li>
<li>
Fully-Functional - end-to-end <em>production-like
functionality</em>, temporary versions of the main application
</li>
<li>
Easily-Deployed - <em>instantly built and deployed</em>
whenever there is a change in an application’s code
</li>
<li>
Self-Contained - <em>isolated from
production</em>, these environments cannot affect production or other review apps and vice versa
</li>
</ul>
<div class="img-wrapper">
<img src="images/diagrams/scenario_3.png" alt="multiple developers w/ review apps" />
</div>
<p>
Your team has now introduced a review app solution like Stagehand to the
mix. With review apps, each developer on your team now has their own
isolated environment where they can easily deploy and share their new
features. This reduces conflicts over shared staging environments.
</p>
<p>
Each review app can be accessed via a unique, shareable URL. Sharing this with your product manager and other non-technical
stakeholders will allow you to get feedback earlier and more quickly.
</p>
<p>
Review apps also enable greater collaboration within your development
team itself. You do not have to pull down each other’s code and get it
running locally to collaborate.
</p>
<p>
This makes checking out your work in a production-like
environment as you are developing as simple as possible.
</p>
<h3>2.4. Collaborative Workflow</h3>
<p>
To understand how review apps look like in the context of GitHub pull requests, we'll walk through a similar scenario.
It starts with you opening a pull request for your new navigation bar feature. The product
manager will have to see the change and give approval before your code
can move on to production.
</p>
<div class="img-wrapper">
<img src="images/diagrams/wireframe_1.png" alt="github pull request with one review app" />
</div>
<p>
As soon as the pull request is opened, a review app is automatically
built and deployed for you, and it can be accessed with a unique URL. You share this review app with
your product manage but they want you to move the navigation bar icon to
the other side of the page.
</p>
<div class="img-wrapper">
<img src="images/diagrams/wireframe_2.png" alt="github pull request with two review app" />
</div>
<p>
After updating some code and making a new commit to the same branch, a whole new review app is built and deployed. Both review apps are live simultaneously enabling you to
open each one and compare them
side-by-side.
</p>
<p>
You share the link for the new review app with your product manager, and after approval you are clear to merge your changes to production. When this pull request is
closed, all review apps associated with it will be automatically
disposed of which will free up any unnecessary cloud resources.
</p>
<h2 id="frontend-review-apps">3. Frontend Review Apps</h3>
<p>
Now that we understand what review apps are and what their value is, we will
take a look at what we mean when we say that Stagehand is for <em>modern frontend
applications</em>.
</p>
<h4>3.1. Why Frontend Review Apps?</h4>
<p>
Frontend review apps are an incredibly helpful tool for developers.
</p>
<p>
<em>First</em>, they deal heavily with the <em>end user
experience</em> so more visual testing and verification in a deployed
environment is needed. You want to be able to mimic the eventual user
experience as much as possible during development.
</p>
<p>
<em>Second</em>, they are more <em>lightweight</em>. They do
not need to spin up as much infrastructure nor allocate as many
resources as a full stack application. Also, because frontend
applications are decoupled from data level concerns, they better mimic
the final production environment as a full stack application.
</p>
<p>
<em>Finally</em>, because the functionality of frontend applications are more
user or consumer facing, there may need to be more <em>input from non-technical stakeholders</em>. You need a
way to easily deploy and share your latest changes with them during
development.
</p>
<h4>3.2. Frontend Applicaton Architecture</h4>
<p>
To give some context for what type of architecture we are for, we'll contrast it first with a traditional 3-tier full stack web architecture.
</p>
<div class="sequence">
<div class="img-wrapper">
<img src="images/diagrams/fullstack-1.png" alt="fullstack diagram flow 1" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/fullstack-2.png" alt="fullstack diagram flow 2" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/fullstack-3.png" alt="fullstack diagram flow 3" />
</div>
</div>
<p>
First, a client requests an asset from an application, that request is first
handled by the web server. Then the application server will handle the
business logic for the application, including fetching data from the
database and generating the assets for the response. Finally, the
response is sent back to the client, generally HTML, CSS, and
JavaScript files.
</p>
<p>
<em>The key takeaway from this full stack architecture is that the assets
are generated at request time</em>. So it is only when the client requests
our application that the assets are actually built. This is in
contrast to what happens in a frontend application.
</p>
<p>
In a decoupled frontend application architecture, such as a site built with a
static site generator, things happen in the opposite direction:
</p>
<div class="sequence">
<div class="img-wrapper">
<img src="images/diagrams/ssg-1.png" alt="ssg flow 1" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/ssg-2.png" alt="ssg flow 2" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/ssg-3.png" alt="ssg flow 3" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/ssg-4.png" alt="ssg flow 4" />
</div>
</div>
<p>
In this architecture, when a change is made to the codebase of the
application the assets are automatically built. Then those pre-built
assets are typically pushed to a content delivery network (CDN) for
hosting, replacing old versions of the assets. When a client makes a request for the application, these
latest pre-built assets can be instantly served from an edge location
on the CDN.
</p>
<p>
<em>Stagehand supports frontend applications like this that can be
pre-built and instantly served from a CDN</em>.
</p>
<div class="sequence">
<div class="img-wrapper">
<img src="images/diagrams/jamstack-1.png" alt="jamstack flow 1" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/jamstack-2.png" alt="jamstack flow 2" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/jamstack-3.png" alt="jamstack flow 3" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/jamstack-4.png" alt="jamstack flow 4" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/jamstack-5.png" alt="jamstack flow 5" />
</div>
</div>
<p>
Modern dynamic frontend applications take the previous architecture a step further. They both are pre-built and served from a CDN.
</p>
<p>
However with modern dynamic frontend applications, more complex
client-side JavaScript is sent back to the client in the response.
Then <em>data can be fetched and rendered by client-side code using external APIs</em>.
These APIs could be third party such as Stripe, Auth0, Firebase or
your own custom built API. This gives these applications more dynamic
functionality, similar to a full stack application.
</p>
<p>
If you're familiar with JAMstack[<a href="#footnote-5">5</a>] or Single Page Applications (SPAs), they fall under this category. Stagehand also supports these.
</p>
<h2 id="existing-solutions">4. Existing Solutions</h2>
<p>
There are
generally two categories of existing review apps solutions: <em>feature solutions</em> and
<em>service solutions</em>.
</p>
<h3>4.1. Feature vs. Service Solutions</h3>
<p>
Feature solutions (Reviews As A Feature) offer review app
functionality as part of a larger hosting service. In order to take
advantage of their review apps feature, you typically must host your
entire application on their hosting service. Examples include Netlify
with their “Deploy Previews” feature, Vercel with their “Preview
Deployments” feature, and Heroku with their “Review Apps” feature.
</p>
<p>
Service solutions (Reviews As A Service) exist specifically for
providing review apps for developers. They provide developers review
app functionality without having to host their entire application on
their platform. There are a wide range of examples here as well,
including FeaturePeek, Release, and Tugboat.
</p>
<div class="img-wrapper">
<img src="images/diagrams/table-1.png" alt="tradeoffs table 1" />
</div>
<p>
Neither of these types of solutions are truly open source. They do not
give you control over the infrastructure or code used to manage your
review apps. However, they are both very convenient solutions as they
automate the deployment and management of review apps for you.
</p>
<p>
Service solutions are more flexible as they specialize in review apps
and do not tie developers to a larger service. But both solutions host
your review apps for you and are feature-rich right out of the box.
</p>
<h3>4.2. DIY</h3>
<p>
If you wanted to self-host review apps and have the control of an open source solution you would have to provision and configure a rather large
number of resources:
</p>
<div class="img-wrapper">
<img src="images/diagrams/DIY.png" alt="DIY diagram" />
</div>
<p>
You will need a cloud storage solution to store all of the
build assets for each of your review apps. Then you will need to
provision and configure a CDN (content delivery network) for secure
and fast hosting. For any processing needs such as routing, you may
have to write and deploy a number of serverless functions.
</p>
<p>
The most extensive resource that you will have to provision and
configure is a build server. You will have to set it up to automate
the building, deploying, and tearing down of your review apps. You
will also have to integrate it with some version control platform, such as GitHub. Finally, you will need some
services to secure your review apps according to your needs.
</p>
<div class="img-wrapper">
<img src="images/diagrams/table-2.png" alt="tradeoffs table 2" />
</div>
<p>
The DIY approach gives us all of the benefits of open source as we now
own the infrastructure and code. However, provisioning and configuring so
many resources to get review apps up and running is far from
convenient. DIY has the same flexibility as Reviews as a Service but it won't be feature rich right out of the box.
</p>
<div class="img-wrapper">
<img src="images/diagrams/table-3.png" alt="tradeoffs table 3" />
</div>
<p>
Stagehand gives you the same tradeoffs as the DIY approach with one key difference. We automate
provisioning and configuration of all of the infrastructure and setup for you. Stagehand is fully open source,
giving you control of your self-hosted infrastructure and code. As a bonus we also provide you with a dashboard wrapper for each of your review apps.
</p>
<div class="sequence">
<div class="img-wrapper">
<img src="images/diagrams/wireframe_2.png" alt="pull request wireframe" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/stagehand-pr-demo.png" alt="stagehand pull request demo" />
</div>
</div>
<p>
Stagehand provides the same collaborative workflow that we went over earlier, reducing friction in your development process.
</p>
<h2 id="building-stagehand">5. Building Stagehand</h2>
<p>
Stagehand is built to be integrated directly with GitHub pull
requests. We also provide a CLI which we'll get into later in the case
study. Stagehand is agnostic to any frontend that can be
pre-built and served from a CDN. This includes frameworks such as
Gatsby, Next, Hugo, React, etc.
</p>
<p>
We built Stagehand in such a way to be less-dependent on if frameworks
change certain configurations or if a new hot framework shows up on
the market. We ask for your build commands and how your app outputs
its HTML assets. This is all the information we need to set up your
local repository. Let's dive into how we built it.
</p>
<div class="img-wrapper">
<img src="images/diagrams/final-architecture.png" alt="Stagehand final architecture" />
</div>
<p>
Stagehand is divided into 3 components: AWS Infrastructure, GitHub
Actions, and Client-side code. We'll go through them in that order so
you'll be able to fully understand each piece seen in the diagram
above.
</p>
<h2 id="aws">6. AWS</h3>
<div class="img-wrapper">
<img src="images/diagrams/aws-final.png" alt="Final aws architecture" />
</div>
<p>
There are two flows through our AWS infrastructure. The first is when
review apps are being created or torn down. The second is when someone
views a review app.
</p>
<h4>6.1. S3 Bucket</h4>
<p>
The S3 Bucket is our storage solution. It is an object store for our files.
This is where each of our review apps for a particular Stagehand
application are stored in its entirety. The review apps stored will
have identical files. For example, each review app for a specific app will have an
<code>index.html</code> file. This means we need a way for the review
apps to be differentiated from one another. We need to make sure all
<code>index.html</code> files are uniquely name spaced, and that it is
uniquely name spaced together with all the other assets for that
review app.
</p>
<div class="img-wrapper">
<img src="images/diagrams/aws-s3.png" alt="Branch/Commit identifier" />
</div>
<p>
To handle this we group review apps by the branch name in which the
feature is being worked on and a hash of the commit. This approach
helps us in two ways. The first is that the branch gives context as to
what feature is being developed and it allows us to group review apps
logically by feature being worked on. The commit hash identifier will
then ensure that each review app has a unique namespace within the s3
bucket.
</p>
<h4>6.2. CloudFront</h4>
<div class="img-wrapper">
<img src="images/diagrams/aws-cloudfront.png" alt="Aws cloudfront flow" />
</div>
<p>
We use CloudFront as our CDN and hosting solution. All incoming HTTP
requests for review apps first go through CloudFront.
If the Cloudfront edge location has the requested
resource cached, it will be quickly returned to the user.
If Cloudfront is empty or expired, then
it retrieves the correct asset from the S3 Bucket and returns
it to the user. The bonus of using CloudFront is that it handles
securing requests with TLS and provides us with an out of the box
domain to use. There’s no need to configure DNS, get an SSL
certificate, or link CloudFront to an existing domain.
</p>
<h4>6.3. IAM</h4>
<div class="img-wrapper">
<img src="images/diagrams/aws-iam.png" alt="Aws iam flow" />
</div>
<p>
The last AWS infrastructure piece is Identity and Access Management
(IAM). During <code>stagehand init</code> we create credentials for
you that have strict access controls. Those are the credentials used in your
GitHub repository as well. This enables us to tightly secure the access to
CloudFront and S3. It also ensures that the AWS credentials that are
used to spin up the infrastructure can’t access any other AWS
resources on the account where this infrastructure is located. The
developer who initialized Stagehand to the repository now doesn’t have
to worry about what individuals have access to the repository,
whether or not they are malicious, etc.
</p>
<h4>6.4. CloudFormation</h4>
<div class="img-wrapper">
<img src="images/diagrams/aws-cloudformation.png" alt="Aws cloudformation flow" />
</div>
<p>
To deploy our AWS infrastructure we used CloudFormation. It allows us
to use a template with listed resources, configuration, and outputs.
It will spin up a CloudFormation Stack with all the infrastructure
we need. We didn’t need to customize each CloudFormation Stack to each
Stagehand app, so a template was a perfect approach. This also allows
us to use the outputs that this CloudFormation Stack creation gives us
to automate setting up the users GitHub account with the proper
configuration. Another bonus of having all of our resources grouped
together is not only the ease of spinning it up, but also of tearing
it down.
</p>
<h2 id="github-actions">7. GitHub Actions</h3>
<p>
GitHub Actions [<a href="#footnote-6">6</a>] is a fairly new tool offered by GitHub.
It was launched only a couple of years ago, and has been
continuously improving over that time. With this feature in its
infancy, it may help to first understand why GitHub created it before
we move onto how it actually functions.
</p>
<h4>7.1 Why Does Github Actions Exist?</h4>
<p>
To understand why GitHub Actions exists and the problem it solves,
we’ll go over a very common scenario for a GitHub user: You want to
build your Gatsby application (a framework for building frontend apps)
every time a commit to your repository is made. To make this happen
what would you need to do?
</p>
<div class="sequence">
<div class="img-wrapper">
<img src="images/diagrams/gh-gatsby-fail-1.png" alt="Gatsby fail 1" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/gh-gatsby-fail-2.png" alt="Gatsby fail 2" />
</div>
</div>
<p>
The repository itself can’t run the code needed to build the Gatsby
app. This is because the repository does not have a runtime.
We need some place with a runtime for the Gatsby build to be executed.
</p>
<div class="img-wrapper">
<img src="images/diagrams/gh-buildserver.png" alt="Gatsby build server" />
</div>
<p>
We can solve this by having a server receive a
notification from GitHub letting us know when to start the build
process. Then we’d pull down the code from the repository onto the
server and run the build command. This is a lot of work to setup
a seemingly simple task.
</p>
<p>
GitHub noticed that running code in the context of their
repository was an incredibly common flow of events its
users would want to execute. GitHub wanted to devise a way for you to run code directly
within your repository and eliminate the need to spin up or configure
your own server. This inspired the creation of GitHub Actions.
</p>
<div class="img-wrapper">
<img src="images/diagrams/gh-buildrepo.png" alt="Gatsby GitHub Actions build" />
</div>
<p>
There is now a way to run code within the context of your repository.
GitHub provides each repository access to a server on which it can
run code in response to GitHub events.
</p>
<p>
If you recall, the events we’re concerned about (pull requests,
commits) are repository level events. GitHub Actions is perfect for
our use case because we can leverage the server GitHub provides us to
build our review apps.
</p>
<h4>7.2. Using GitHub Actions</h4>
<p>
The only piece of information that needs to be provided to GitHub so
that it knows when and how to run the code is a workflow file. These
workflow files will live in your GitHub repository under a special
folder
<code>.github</code> to alert GitHub to check for the workflow files.
We automatically provide all the workflow files that a user of Stagehand needs
during setup.
</p>
<div class="sequence">
<div class="img-wrapper">
<img src="images/diagrams/GitHub-Actions-flow-1.png" alt="GitHub Actions flow 1" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/GitHub-Actions-flow-2.png" alt="GitHub Actions flow 2" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/GitHub-Actions-flow-3.png" alt="GitHub Actions flow 3" />
</div>
<div class="img-wrapper">
<img src="images/diagrams/GitHub-Actions-flow-4.png" alt="GitHub Actions flow 4" />
</div>
</div>
<p>
The above is the flow of a GitHub Action that is separated into four
steps: the event, the event listener, provisioning the server, and
the execution of the workflow file.
</p>
<p>
Let's look at those four steps in the context of when Stagehand's
<code>create_review_app.yml</code> workflow file is run.
</p>
<ol>
<li>
A pull request is created in your repository
</li>
<li>
GitHub will see that the <code>create_review_app.yml</code> workflow file inside your
repository is listening for when pull requests are created and will thus
trigger the workflow to begin.
</li>
<li>
GitHub will provision a server for you that is set up with the
appropriate environment credentials specified in <code>create_review_app.yml</code>.
</li>
<li>
GitHub server will then execute the contents of
<code>create_review_app.yml</code>. This will build the review app,
copy the build to an S3 Bucket, and publish a comment containing the URL of
the review app.
</li>
</ol>
<p>
We also provide one more workflow file that will be triggered when a pull
request is closed or merged. This will tear down any review apps
associated with that branch and invalidate CloudFront’s cache so the
review apps will no longer be accessible.
</p>
<h2 id="client-side-code">8. Client Side Code</h3>
<div class="img-wrapper">
<img src="images/diagrams/client-overview.png" alt="Client overview" />
</div>
<p>
Let's look at an overview of the pieces in our client-side code. There
are three fundamental parts: the customizable dashboard (as seen by
the banner providing some context about the review app), the iframe
(to serve the review app content), and the Service Worker (to handle
all HTTP communication coming in and out of the iframe). All this code
lives in an HTML file and two JavaScript files that we place in
every review app automatically.
</p>
<h3>8.1. Dashboard and Iframe</h3>
<div class="img-wrapper">
<img src="images/diagrams/client-dashboard.png" alt="Client dashboard" />
</div>
<p>
The HTML file provides the scaffolding for a dashboard. The Stagehand
dashboard visually sits on top of the review app to give extra context
to the viewer of the review app. It reminds the viewer that they’re
looking at a review app and not production. While the information that
our dashboard gives at the moment is a banner, this setup allows the
user of Stagehand to easily build out a custom dashboard to do and say
whatever they want. This could be done by building out custom dashboard
content and hosting it on another domain. You could then link to it in
your provided Stagehand HTML file. Alternatively, your custom dashboard
can be built directly within the provided HTML and JavaScript files.
</p>
<p>
To get this dashboard to sit on top of the review app without
interfering with it we use an iframe.
</p>
<blockquote>
“The iframe represents a nested browsing context, embedding another
HTML page into the current one.” [<a href="#footnote-7">7</a>]
</blockquote>
<div class="img-wrapper">
<img src="images/diagrams/client-iframe.png" alt="Client iframe" />
</div>
<p>
It is basically a webpage within another webpage that is created with just a
simple HTML tag. We have styled it so that it looks as though it’s the
main window itself rather than a tag within the main window. Another feature of an
iframe is that if the main window is the same origin (ie
<code>https://1245.cloudfront.net</code>) as the iframe, then the main
window can access certain properties of the iframe like its content
and location. We use this feature of the iframe to solve an important
issue later on.
</p>
<h3>8.2. Service Workers and Routing</h3>
<p>
Those familiar with Service Workers may notice that we’re using them
in an unorthodox way. More often than not they’re used for Progressive
Web Apps [<a href="#footnote-8">8</a>] [<a href="#footnote-9">9</a>].
They take advantage of many
browser APIs like the built in Cache and Database options to serve app
content quickly and enable offline use. Most of this information about
Service Workers is not relevant in order to understand how we’re using them.
Therefore, we are only going to talk about them in the context that they’re
being used.
</p>
<div class="img-wrapper">
<img src="images/diagrams/client-serviceworker.png" alt="Client service worker" />
</div>
<p>
A Service Worker [<a href="#footnote-10">10</a>] is a browser feature. It is not infrastructure. It is
code that is run inside a browser process. Once it is registered to a
domain, such as <code>1245.cloudfront.net</code>, it intercepts all
requests going in and out of that domain. We can both alter the
request and response in the cycle. In our case we’re going to
intercept and alter HTTP requests.
</p>
<p>
The important takeaways for how we’re using them is to know that they
are an in-browser proxy and they are able to send and receive
messages to the domain that they are registered to. We are only using them
to make sure each request coming out of the review app has
the correct path.
</p>
<h3>8.3. Viewing the Review App</h3>
<div class="img-wrapper">
<img src="images/diagrams/client-createapp.png" alt="Client build app flow" />
</div>
<p>
Before we begin walking through the client request cycle, we need to
revisit the GitHub Server and its interactions with our AWS infrastructure.
Now that we have client files in the mix,
we need to add both the review app build and the Stagehand client
files to the S3 Bucket. This means that each review app will have its
own version of the Stagehand Client files. These client files are very
small and have no outside dependencies.
</p>
<p>
Once our app is built and all of the appropriate review app files are
in the S3 Bucket, we can view the review app. The below images show
how this process occurs.