-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
2011 lines (1965 loc) · 140 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">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://use.typekit.net/jor7uma.css" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/index.css" />
<link rel="icon" href="images/favicon.svg" type="image/svg" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Bodoni+Moda:ital,opsz,wght@0,6..96,400..900;1,6..96,400..900&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap"
rel="stylesheet"
/>
<script src="js/script.js" defer></script>
<title>Campfire</title>
</head>
<body>
<header class="transparent-background">
<a href="#landing-wrap">
<img alt="campfire-logo" src="images/logo.svg" />
</a>
<nav>
<a href="#case-study-content">case study</a>
<a href="#team">team</a>
<a href="https://github.com/campfire-previews">github</a>
</nav>
</header>
<div id="landing-wrap">
<section id="landing">
<!-- <div class="twinkling"></div> -->
<div id="landing-title">
<h2>open-source, self-hosted</h2>
<h1 class="gradient">Collaborative</h1>
<h1>Deploy Previews</h1>
</div>
<div id="landing-video">
<a data-fslightbox="gallery" href="/media/campfire-demo-v1.mp4">
<svg
width="132"
height="132"
viewBox="0 0 132 132"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="66" cy="66" r="66" />
<path
d="M90.8506 67.9255L53.4623 89.5117L53.4623 46.3394L90.8506 67.9255Z"
fill="#151A31"
/>
</svg>
</a>
<div>
<img src="/images/video-preview.png" alt="video-preview" />
<p>watch our 45-second demo!</p>
</div>
</div>
<!-- <a href="#case-study-content" id="cta">read our case study</a> -->
</section>
</div>
<div id="rock-wrapper">
<div id="rock-right"></div>
<div id="rock-left"></div>
<section id="landing-features"></section>
</div>
<a id="navigate-top-button" href="#landing-wrap">
<img src="images/up-arrow.svg" alt="up-arrow" />
</a>
<section id="features">
<article id="features-wrapper">
<div class="feature">
<img
class="gif right"
src="images/features/pull-request.gif"
alt="GIF of pull request"
/>
<div class="text">
<h2>
automatically spin up a new deploy preview for each new
pull-request
</h2>
<p>
Each deploy preview showcases the commit with the proposed
changes. Accessible through a public URL, it directs users to
their specific deploy environment, which is equipped with
Campfire’s comprehensive suite of feedback tools.
</p>
</div>
</div>
<div class="feature">
<img
class="gif"
src="images/features/comments.gif"
alt="GIF of comment feature"
/>
<div class="text">
<h2>
get <span>both</span> technical and non-technical stakeholders
involved early in the development cycle
</h2>
<p>
Designers, QA testers, and product managers can review and comment
on proposed changes directly within the Campfire feedback
interface, ensuring feedback from all relevant stakeholders is
integrated early in the development process.
</p>
</div>
</div>
<div class="feature">
<img
class="gif right"
src="images/features/session-replay.gif"
alt="GIF of session replay feature"
/>
<div class="text">
<h2>
get <span>context-rich</span> feedback with session replay,
browser and screen-size information
</h2>
<p>
This data helps engineers pinpoint exactly when and where issues
arise, leading to more accurate feedback. These insights are
essential for optimizing user experiences across various devices
and browsers, guaranteeing a seamless interface for all users.
</p>
</div>
</div>
<div class="feature">
<img
class="gif"
src="images/features/campfire-cli-clip.gif"
alt="GIF of campfire cli"
/>
<div class="text">
<h2>
effortless installation and configuration with the Campfire
<span>CLI</span>
</h2>
<p>
The Campfire CLI makes it quick and straightforward to get started
setting up deploy previews, so you can focus more on development
and less on configuration.
</p>
</div>
</div>
</article>
</section>
<section id="features-case-study"></section>
<section id="case-study">
<h1>case study</h1>
<!-- CASE STUDY TOC -->
<div id="case-study-content">
<aside id="toc">
<ul>
<li data-section="Introduction">
<a href="#section-1-Introduction">Introduction</a>
</li>
<li class="subitem" data-section="Introduction">
<a href="#section-1-1-Terms">Terms</a>
</li>
<li data-section="The Problem">
<a href="#section-2-The-Problem">The Problem</a>
</li>
<li class="subitem" data-section="The Problem">
<a href="#section-2-1-Deploy-Previews">Deploy Previews</a>
</li>
<li class="subitem" data-section="The Problem">
<a href="#section-2-2-Limitations-of-Deploy-Previews"
>Limitations of Deploy Previews</a
>
</li>
<li data-section="Existing Solutions">
<a href="#section-3-Existing-Solutions">Existing Solutions</a>
</li>
<li class="subitem" data-section="Existing Solutions">
<a href="#section-3-1-Deploy-Previews-as-a-Feature"
>Deploy Previews as a Feature</a
>
</li>
<li class="subitem" data-section="Existing Solutions">
<a href="#section-3-2-Livecycle">Livecycle</a>
</li>
<li class="subitem" data-section="Existing Solutions">
<a href="#section-3-3-DIY">DIY</a>
</li>
<li data-section="Introducing Campfire">
<a href="#section-4-Introducing-Campfire">Introducing Campfire</a>
</li>
<li class="subitem" data-section="Introducing Campfire">
<a href="#section-4-1-Who-Campfire-is-For">Who Campfire is For</a>
</li>
<li class="subitem" data-section="Introducing Campfire">
<a href="#section-4-2-Campfire-Features">Campfire Features</a>
</li>
<li data-section="Developing Campfire">
<a href="#section-5-Developing-Campfire">Developing Campfire</a>
</li>
<li class="subitem" data-section="Developing Campfire">
<a href="#section-5-1-Automating-Deploy-Previews"
>Automating Deploy Previews</a
>
</li>
<li class="subitem" data-section="Developing Campfire">
<a href="#section-5-2-Accessing-Deploy-Previews"
>Accessing Deploy Previews</a
>
</li>
<li class="subitem" data-section="Developing Campfire">
<a href="#section-5-3-Feedback-Interface">Feedback Interface</a>
</li>
<li class="subitem" data-section="Developing Campfire">
<a href="#section-5-4-Data-Storage">Data Storage</a>
</li>
<li data-section="Future Work">
<a href="#section-7-Future-Work">Future Work</a>
</li>
<li data-section="References">
<a href="#section-8-References">References</a>
</li>
</ul>
</aside>
<!-- CASE STUDY SECTIONS -->
<article>
<section id="section-1-Introduction" data-section="Introduction">
<h1>1 - Introduction</h1>
<p>
Campfire is an open-source, self-hosted, collaborative
deploy-preview solution for containerized, headless frontends.
Much like the way an actual campfire brings people together to
trade stories, Campfire aims to be a central place for
cross-functional teams to visually review and discuss proposed
code changes or bug fixes early in the software development cycle.
</p>
<p>
<img
src="images/case-study/01.png"
alt="Campfire brings teams together"
/>
</p>
<p>
Campfire generates a deploy preview for each pull request,
showcasing the latest commit with the proposed changes, which can
be accessed through a public URL. The URL directs users to their
deploy preview, equipped with Campfire's suite of comprehensive
feedback tools.
</p>
<p>
Integrating a feedback interface directly into the deploy preview
simplifies collaboration between teams and addresses common
bottlenecks that delay project timelines.
</p>
</section>
<section id="section-1-1-Terms" data-section="Terms">
<h2>1.1 - Terms</h2>
<p>
In this case study, we'll frequently reference the following
technical terms:
</p>
<ul>
<li>
<strong>Client App</strong> - The codebase of the user,
retrieved from the repository when initiating a new pull request
or when a new commit is made to the same pull request.
</li>
<li>
<p>
<strong>Deploy Preview</strong> - The ephemeral infrastructure
provisioned to host a live preview of the Client App for each
pull request. Also known as ephemeral environments, preview
environments, or preview apps.
</p>
</li>
<li>
<p>
<strong>Feedback Interface</strong> - A relatively new
component of some deploy preview solutions, which provides an
overlay for user collaboration and feedback on the previewed
changes.
</p>
</li>
</ul>
</section>
<section id="section-2-The-Problem" data-section="The Problem">
<h1>2 - The Problem</h1>
<p>
In the early days of web development, software engineers often
made live changes directly on production servers, a risky practice
that could easily break the website or service.
</p>
<p>
As the industry matured, developers began adopting version control
systems like Git and SVN to better manage and track code changes.
However, these systems did not solve the problem of testing
changes in a controlled environment before production deployment.
<br />
<a class="reference" href="#section-8-References">1</a>
<a class="reference" href="#section-8-References">2</a>
</p>
<p>
The rise of agile development and continuous
integration/continuous deployment (CI/CD) practices led to the
adoption of staging environments. These environments allowed teams
to test code in settings that closely mirrored their production
environment, enabling them to identify and fix bugs without
affecting the live application. Despite the benefits, staging
environments introduced significant bottlenecks. Multiple
developers often pushed their changes to a single staging
environment simultaneously, leading to conflicts and resource
contention. This not only caused delays and increased security
risks but also led to bugs and higher operational costs.
<a class="reference" href="#section-8-References">3</a>
</p>
<p>
<img
src="images/case-study/staging-blocked.png"
alt="Bottleneck"
/>
</p>
<p>
The process of resolving bugs found in staging involves several
structured steps, especially when using tools like GitHub:
</p>
<ol>
<li>
<strong>Branch Creation</strong> - Developers create a new
branch from the main codebase, allowing them to address bugs
without impacting the stable production version.
</li>
<li>
<strong>Commit Changes</strong> - Necessary fixes are made and
committed to the branch, with detailed commit messages
explaining the changes.
</li>
<li>
<strong>Push to Repository</strong> - The branch is then pushed
to the remote repository on GitHub.
</li>
<li>
<strong>Create Pull Request</strong> - A pull request is opened
against the main branch for merging the fixes and facilitating
code review.
</li>
<li>
<strong>Code Review and Approval</strong> - The pull request is
reviewed by team members who may suggest or request changes.
</li>
<li>
<strong>Merge and Deploy to Staging</strong> - After approval,
the changes are merged and deployed to the staging environment
to verify the bug fix.
</li>
<li>
<strong>Testing in Staging</strong> - The application is tested
in staging to ensure the fix is effective and no new issues have
arisen.
</li>
<li>
<strong>Push to Production</strong> - Once confirmed, the
changes are deployed to production.
</li>
<li>
<strong>Monitoring</strong> - Post-deployment the application is
monitored for any unexpected issues.
</li>
</ol>
<p>
If bugs are detected during staging tests, the process from branch
creation to staging deployment may need to be repeated to ensure
all issues are thoroughly addressed.
<br />
<a class="reference" href="#section-8-References">4</a
><a class="reference" href="#section-8-References">5</a
><a class="reference" href="#section-8-References">6</a>
</p>
<p>
Historically, non-engineering team members such as UI designers,
QA testers, marketers, and product managers had limited
opportunities to view and provide feedback on proposed changes
until late in the development process. Often, they only saw these
changes when they were moved to the staging or production
environments.
</p>
<p>
This delay not only prevented timely feedback that could influence
design and functionality but also excluded these key stakeholders
from early stages of project discussions. Additionally, the lack
of a dedicated feedback mechanism in earlier development stages
meant that their insights, which could significantly impact user
experience and product success, were often underutilized or
solicited too late to make meaningful adjustments without
time-consuming revisions.
<a class="reference" href="#section-8-References">7</a>
</p>
<p>
<img
src="images/case-study/02.png"
alt="Before deploy previews dev cycle"
/>
</p>
</section>
<section
id="section-2-1-Deploy-Previews"
data-section="Deploy Previews"
>
<h2>2.1 - Deploy Previews</h2>
<p>
Deploy previews were introduced as a solution to streamline the
code review process, allowing engineers to view changes earlier in
the development process without the need to manually pull down
code or wait for access to a staging environment. This drastically
shortened the cycle between identifying bugs and deploying fixes,
enabling faster iterations and more efficient development.
</p>
<p>
Deploy previews also provided an accessible platform for
non-engineering team members to view proposed changes. This
expanded the review process to a broader group of stakeholders and
enabled collaboration across different teams. Despite their
effectiveness in demonstrating code changes, deploy previews
initially lacked integrated tools for submitting feedback directly
within the previews.
</p>
<p>
<img
src="images/case-study/03.png"
alt="Introduction of deploy previews into dev cycle"
/>
</p>
</section>
<section
id="section-2-2-Limitations-of-Deploy-Previews"
data-section="Limitations of Deploy Previews"
>
<h2>2.2 - Limitations of Deploy Previews</h2>
<p>
While deploy previews were adept at showcasing code changes, they
lacked an interface to provide feedback to the proposed changes
within the same application. This forced users to use third-party
tools to provide feedback on the proposed changes, like Slack and
GitHub for comments or Loom and Zight (formerly CloudApp) for
screen recordings, or Zoom for synchronous video calls. The
absence of a unified feedback interface often led to scattered
comments across many different platforms, complicating the
aggregation and tracking of feedback, and often causing the
context to be lost.
</p>
<p>
Comments made across multiple different platforms led to
disjointed communication, complicating the feedback process. Even
if developers consolidated discussions on GitHub, non-engineering
team members, such as project managers, designers, and QA
personnel, were often left out of the loop. They often don’t have
GitHub accounts and would seek a straightforward way to comment on
visual changes. Not having a built-in, accessible feedback system
in deploy previews made it harder to collaborate and quickly fix
problems.
<a class="reference" href="#section-8-References">8</a>
</p>
<p>
<img
src="images/case-study/04.png"
alt="Overwhelmed and frustrated developer"
/>
</p>
</section>
<section
id="section-3-Existing-Solutions"
data-section="Existing Solutions"
>
<h1>3 - Existing Solutions</h1>
<p>
Several solutions have recently been developed to add a
communication layer to deploy previews, making collaboration more
accessible for non-technical team members. Services like Netlify
Drawer, Vercel Comments, and Livecycle have attempted to bridge
this gap by offering built-in tools for capturing feedback when
the user is viewing proposed changes. Each of these services
presents different tradeoffs, particularly in terms of hosting
options, whether they are open-source, and the ease of setup and
use.
</p>
</section>
<section
id="section-3-1-Deploy-Previews-as-a-Feature"
data-section="Deploy Previews as a Feature"
>
<h2>3.1 - Deploy Previews as a Feature</h2>
<p>
Netlify and Vercel integrate deploy previews within their broader
suite of services, providing a production-like view of changes
pre-deployment. Netlify, primarily a host for static sites and
supports Jamstack projects, includes Netlify Drawer as a feature
available for their deploy previews. Similarly, Vercel is tailored
for frontend frameworks like Next.js, incorporating Vercel
Comments into its regular services, so that non-engineering team
members have the ability to provide feedback on their team’s
deploy previews.
</p>
<p>
Netlify Drawer enhances Netlify’s deploy previews with a feedback
toolbar for screenshots, recordings, and comments. The Drawer
comment feature allows for synchronizing feedback between the
deploy preview and GitHub. Comments can be posted by Netlify
Drawer’s bot if the user does not have a GitHub account.. This
integration includes the user’s browser metadata in comments,
providing context in order to make it easier for developers to
recreate and fix any potential bugs.
</p>
<p>
Vercel’s Comments leverage Liveblocks, a third-party real-time
collaboration tool, allowing users to attach comments directly to
UI elements. This integration improves feedback by allowing more
interactive and detailed discussions. Unlike Netlify, Vercel syncs
their comments with Slack rather than GitHub.
</p>
<div class="multiple-images">
<p>
<img
src="images/case-study/vercel-comments.png"
alt="Screenshot of Vercel's Comments"
data-group="preview-as-a-feature"
/>
</p>
<p>
<img
src="images/case-study/netlify-drawer.png"
alt="Client requesting resources using path routing from the application load balancer"
data-group="preview-as-a-feature"
/>
</p>
</div>
<p>
These services, while feature-rich, come with the caveat of
requiring full application hosting on their platforms, limiting
flexibility for teams who prefer independent control over their
deployment.
</p>
</section>
<section id="section-3-2-Livecycle" data-section="Livecycle">
<h2>3.2 - Livecycle</h2>
<p>
Livecycle's preview environments are the core of their project
offering. Livecycle offers a unique combination of deploy previews
and collaborative tools through its products, Preevy and a product
also named Livecycle. Preevy manages preview environments via
CI/CD workflows or an SDK for external hosting. Livecycle
integrates a feedback interface enabling commenting, HTML/CSS
suggestions, and visual edit comparisons. Additionally, Livecycle
provides debugging tools like screen size adjustments, rudimentary
dev tools, and console access. Its session replay feature
automatically captures user interactions within the preview
environment, offering a replayable video that begins recording
from the moment the user visits the deploy preview.
</p>
<p>
<img
src="images/case-study/livecycle.png"
alt="screenshot of livecycle(cropped)"
/>
</p>
</section>
<section id="section-3-3-DIY" data-section="DIY">
<h2>3.3 - DIY</h2>
<p>
A custom-built deploy preview solution offers a team complete
control over their development and review process. This building
process can be divided into two main parts: the deploy preview
functionality and the feedback system, together encompassing up to
40 steps or more.
</p>
<p>
Implementing such a custom solution requires dedicated teams of
engineers, integration with existing tools, and ongoing
maintenance. The complexity and resource demands can make it
overwhelming and impractical for organizations lacking extensive
technical expertise in automating workflows and managing cloud
service resources.
</p>
<p>
<img
src="images/case-study/05.png"
alt="Exhaustive list of steps for DIY"
/>
</p>
</section>
<section
id="section-4-Introducing-Campfire"
data-section="Introducing Campfire"
>
<h1>4 - Introducing Campfire</h1>
<p>
Campfire removes the trouble of building a DIY solution from
scratch while still providing organizations control over their
data, and allowing integration into an existing CI/CD pipeline.
Our primary goal was to design a feedback interface that
integrates seamlessly with the deploy preview, ensuring
stakeholders can provide feedback without switching contexts. This
interface supports comments and session replays and allows the
capture of contextual data to enhance understanding. Although not
as feature and integration-rich as solutions like Livecycle,
Netlify Drawer, and Vercel, Campfire offers an open-source
alternative with comments that sync to a GitHub pull request and
the ability to record sessions, providing context-rich feedback
directly within the deploy preview.
</p>
<p>
<img
src="images/case-study/tradeoffs-table.png"
alt="Table comparing existing deploy preview solutions"
/>
</p>
</section>
<section
id="section-4-1-Who-Campfire-is-For"
data-section="Who Campfire is For"
>
<h2>4.1 - Who Campfire is For</h2>
<p>
Campfire is designed to support front-end applications that meet
the following criteria:
</p>
<ul>
<li>Hosted on GitHub</li>
<li>Contain a Dockerfile</li>
<li>
Operate independently of a backend or interact with an external
backend via APIs.
</li>
<li>Targeted towards small or early-stage teams</li>
</ul>
<p>
Campfire is not designed to support the following types of
applications:
</p>
<ul>
<li>Hosted on GitLab or other developer platforms</li>
<li>
Require a container image to be generated from source code
</li>
<li>Monolithic architecture</li>
<li>Multi-container applications</li>
</ul>
</section>
<section
id="section-4-2-Campfire-Features"
data-section="Campfire Features"
>
<h2>4.2 - Campfire Features</h2>
CLI tool to simplify the installation and configuration of Campfire:
<div class="gif">
<img
src="images/features/campfire-cli-clip.gif"
alt="GIF of CLI"
/>
</div>
Integration with GitHub automates the creation, update, and
dismantling of preview environments:
<div class="gif">
<img
src="images/features/pull-request.gif"
alt="GIF of pull request"
/>
</div>
Looks Good to Me (LGTM) Button to quickly approve changes with a
simple acknowledgment (and confetti):
<div class="gif">
<img
src="images/case-study/LGTM-side-by-side.gif"
alt="GIF of LGTM feature with github"
/>
</div>
Comments provide feedback directly on the deploy preview and sync
with the GitHub pull request:
<div class="gif">
<img
src="images/case-study/comments-side-by-side.gif"
alt="GIF of comment feature with github"
/>
</div>
Session Replay to capture user interactions in real-time to
demonstrate issues:
<div class="gif">
<img
src="images/features/session-replay.gif"
alt="GIF of session replay feature"
/>
</div>
</section>
<section
id="section-5-Developing-Campfire"
data-section="Developing Campfire"
>
<h1>5 - Developing Campfire</h1>
<p>
In order to build Campfire, we identified four components of a
collaborative deploy preview solution:
</p>
<ol>
<li>
<strong>Automation</strong> - An automated process to generate
deploy previews for each new pull request, or new commit to an
existing pull-request.
</li>
<li>
<strong>Access</strong> - A reliable and straightforward method
for users to access these previews to view and interact with the
proposed changes.
</li>
<li>
<strong>Feedback Interface</strong> - An integrated feedback
mechanism within the deploy preview to collect and display
feedback, allowing stakeholders to comment and discuss directly
on the preview.
</li>
<li>
<strong>Data Storage</strong> - A place to store and manage
Campfire’s data.
</li>
</ol>
<p>
This diagram is an overview of all the responsibilities we
described and how they interact with each other:
</p>
<p>
<img
src="images/case-study/high-level-overview.png"
alt="Campfire architecture by responsibilities"
/>
</p>
</section>
<section
id="section-5-1-Automating-Deploy-Previews"
data-section="Automating Deploy Previews"
>
<h2>5.1 - Automating Deploy Previews</h2>
<p>
<img
src="images/case-study/automation.png"
alt="Campfire architecture highlighting automation"
/>
</p>
<p>
Campfire’s architecture starts with the automatic deployment of
deploy previews, which are generated for each pull request and
hosted temporarily until the pull request is closed. We faced two
primary decisions in this area:
</p>
<ol>
<li>
How to automatically trigger a deployment when a pull request is
made?
</li>
<li>How to host the client application once deployed?</li>
</ol>
<h3>5.1.1 Automatically Triggering Deployment</h3>
<p>
We initially considered using webhooks to trigger a self-hosted
endpoint whenever a pull request was created by the user. However,
this required deploying a dedicated service to handle webhook
events, which would involve additional resources being provisioned
on the user’s AWS account.
</p>
<p>
We opted instead for GitHub Actions, a CI/CD platform that offers
the flexibility of using either self-hosted or GitHub-hosted
runners to automate workflows. This approach eliminates the need
to manage separate resources for webhook responses. GitHub Actions
automatically provisions an environment to execute our defined
workflows, which handle tasks such as authenticating cloud
services, spinning up the necessary resources for the deploy
preview, and posting the preview URL back to the pull request.
</p>
<p>
Additionally, GitHub Actions manages the lifecycle of the runners,
ensuring they shut down and clean up resources after execution.
This efficiency and integration led us to choose GitHub Actions
for automating the deployment of deploy previews. Consequently, a
fundamental requirement for using Campfire is that the user’s
application must be hosted on GitHub; therefore, we are currently
unable to support users on other platforms like GitLab.
</p>
<p>
<img
src="images/features/pull-request.gif"
alt="Trigger deploy preview using GitHub Actions"
/>
</p>
<h3>5.1.2 Hosting the Client’s Application</h3>
<p>
The next step involved selecting a service to temporarily host the
client application. To accommodate a diverse range of applications
and simplify the deployment process, Campfire chose to support
containerized applications. Containerization packages an
application with its dependencies and configurations into a
standardized unit, or container, ensuring it runs consistently
across any environment.
</p>
<p>
Ensuring that the client application behaves the same way locally
as it does once deployed minimizes bugs related to cross-platform
compatibility issues. By focusing on containerized applications,
we enhance the likelihood of successful deployments regardless of
the specific setup or technology stack of the application.
</p>
<p>
The use of containers required a way to manage their life cycles –
deploying, updating, and terminating containers as pull requests
are opened, updated, or closed. Container orchestration services
provide many features in addition to managing the lifecycle of
containers, including automated scaling and high availability.
Without container orchestration services, manual management of
container lifecycles and scaling would be required, introducing
complexity and potential for error.
</p>
<p>
We selected AWS Elastic Container Service (ECS) because it
simplifies container orchestration and easily integrates with
other AWS services such as the application load balancer used in
Campfire. ECS automates the deployment, scaling, and monitoring of
containers, allowing us to deliver stable and consistent deploy
previews without the burden of managing the orchestration layer
ourselves.
</p>
<p>
While other solutions like Elastic Kubernetes Service (EKS) and
Docker Swarm offer more control and flexibility in managing
containers, they require deep knowledge of their ecosystems and
are feature-rich, which can be excessive for our needs. Given that
Campfire requires orchestration for just a single container per
pull request, the simpler and less complex ECS is more appropriate
than the more powerful but complex alternatives like EKS and
Docker Swarm.
</p>
</section>
<section
id="section-5-2-Accessing-Deploy-Previews"
data-section="Accessing Deploy Previews"
>
<h2>5.2 - Accessing Deploy Previews</h2>
<p>
<img
src="images/case-study/access.png"
alt="Campfire architecture highlighting application load balancer"
/>
</p>
<p>
Access to each deploy preview was the next step for Campfire.
Within our setup with AWS ECS, each deploy preview operates as a
separate task. A task is a running instance of a containerized
application, specified by its CPU, memory, and network settings in
a task definition. Each task is automatically assigned a public IP
that can be used to access the running instance. These public IPs
can change if a task is restarted due to updates, configuration
changes, or scaling operations. To manage the dynamic nature of
public IPs, we implemented an application load balancer.
</p>
<p>
Generally, a load balancer distributes incoming network traffic
across multiple servers. For Campfire, which hosts a single
instance of a client’s application in a container, the load
balancer functions more like a router. It efficiently channels
incoming traffic to our preview tasks, using listeners to direct
traffic according to predefined Campfire rules.
</p>
<p>
The traffic is then routed through these rules to target groups,
which are collections that map to specific ECS tasks, regardless
of their currently assigned IP addresses. Having an application
load balancer means access to Campfire’s deploy previews remains
stable and continuous, even when individual tasks undergo IP
changes due to restarts.
</p>
<p>
<img
src="images/case-study/alb-listener.png"
alt="Load balancer routing to target groups that direct traffic to ECS tasks"
/>
</p>
<p>
When configuring rules for the load balancer’s listener we first
experimented with path-based rules for routing – directing traffic
to specific services based on URL paths, for example,
"/client-app/12" for accessing the preview of pull
request #12. However, this approach proved inadequate due to 404
errors when browsers requested additional resources not accounted
for in the path-based rules.
</p>
<div class="multiple-images">
<p>
<img
src="images/case-study/path-based-rule-1.png"
alt="Client requesting resources using path routing from the application load balancer"
data-group="path-based-rule"
/>
</p>
<p>
<img
src="images/case-study/path-based-rule-2.png"
alt="Client requesting resources using path routing from the application load balancer"
data-group="path-based-rule"
/>
</p>
</div>
<p>
The solution evolved to using host-based routing, where the load
balancer would manage requests to a host like
"client-app-12.preview.campfire.com" as an example,
ensuring all subsequent resource requests for a particular preview
consistently reached the correct service.
</p>
<div class="multiple-images">
<p>
<img
src="images/case-study/host-based-rule-1.png"
alt="Client requesting resources using path routing from the application load balancer"
data-group="host-based-rule"
/>
</p>
<p>
<img
src="images/case-study/host-based-rule-2.png"
alt="Client requesting resources using path routing from the application load balancer"
data-group="host-based-rule"
/>
</p>
</div>
<p>
This method eliminated the 404 issue as the host-based approach
accurately directed all related traffic to the appropriate deploy
preview environment, regardless of the specific resource being
requested.
</p>
</section>
<section
id="section-5-3-Feedback-Interface"
data-section="Feedback Interface"
>
<h2>5.3 - Feedback Interface</h2>
<p>
<img
src="images/case-study/feedback-interface.png"
alt="Campfire architecture with feedback interface and ALB highlighted"
/>
</p>
<p>
Campfire wanted to design a feedback interface that accomplishes a
few things:
</p>
<ul>
<li>
integrates with the deploy preview, so that stakeholders don’t
need to switch contexts to add feedback
</li>
<li>
handles comments, since this is the main way stakeholders can
leave feedback
</li>
<li>
allows the user to capture context, for when text comments alone
aren’t enough
</li>
</ul>