PageSourceSearch

https://www.traviscistatus.com/

html traviscistatus.com collected 2026-10-02 04:25:39 UTC 117,536 bytes, 3,171 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3  <head>
4    <meta http-equiv="X-UA-Compatible" content="IE=edge">
5    <!-- force IE browsers in compatibility mode to use their most aggressive rendering engine -->
6
7    <meta charset="utf-8">
8    <title>Travis CI Status</title>
9    <meta name="description" content="Welcome to Travis CI&#39;s home for real-time and historical data on system performance.">
10
11    <!-- Mobile viewport optimization -->
12    <meta name="HandheldFriendly" content="True">
13    <meta name="MobileOptimized" content="320">
14    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
15
16    <!-- Time this page was rendered - http://purl.org/dc/terms/issued -->
17    <meta name="issued" content="1790915139">
18
19    <!-- Mobile IE allows us to activate ClearType technology for smoothing fonts for easy reading -->
20    <meta http-equiv="cleartype" content="on">
21
22      <!-- Atlassian Sans & Mono Fonts -->
23<link
24  rel="preconnect"
25  href="https://ds-cdn.prod-east.frontend.public.atl-paas.net" />
26<link
27  rel="preload"
28  href="https://ds-cdn.prod-east.frontend.public.atl-paas.net/assets/fonts/atlassian-sans/v3/AtlassianSans-latin.woff2"
29  as="font" type="font/woff2" crossorigin />
30<link
31  rel="preload"
32  href="https://ds-cdn.prod-east.frontend.public.atl-paas.net/assets/font-rules/v5/atlassian-fonts.css"
33  as="style" crossorigin />
34
35    <style>
36  /* Dynamic Font Stack based on Feature Flag */
37    /* Using Atlassian Sans & Mono */
38    :root {
39      --font-stack-a: "Atlassian Sans", "Helvetica Neue", Helvetica, Arial, Sans-Serif;
40      --font-stack-b: "Atlassian Mono", "SFMono-Medium", "SF Mono", "Segoe UI Mono", "Roboto Mono", "Ubuntu Mono", Menlo, Consolas, Courier, monospace;
41    }
42</style>
43
44
45      <link rel="icon" type="image/x-icon" href="//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/27/favicon-3a4bd34c-f8d3-468e-ab94-50c3bef48ddc.png" />
46
47    <link rel="shortcut icon" href='//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/27/favicon-3a4bd34c-f8d3-468e-ab94-50c3bef48ddc.png'>
48
49    <link rel="alternate" type="application/atom+xml" href="https://www.traviscistatus.com/history.atom" title="Travis CI Status History - Atom Feed">
50    <link rel="alternate" type="application/rss+xml" href="https://www.traviscistatus.com/history.rss" title="Travis CI Status History - RSS Feed">
51
52      <!-- Canonical Link to ensure that only the custom domain is indexed when present -->
53      <link rel="canonical" href="https://www.traviscistatus.com">
54
55    <meta name="_globalsign-domain-verification" content="y_VzfckMy4iePo5oDJNivyYIjh8LffYa4jzUndm_bZ"/>
56
57
58    <link rel="alternate" type="application/atom+xml" title="ATOM" href="https://www.traviscistatus.com/history.atom" />
59
60    <!-- Le styles -->
61    <link rel="stylesheet" href="https://dka575ofm4ao0.cloudfront.net/packs/0.a7d86fc6a129fa9540bc.css" media="screen" />
62    <link rel="stylesheet" href="https://dka575ofm4ao0.cloudfront.net/assets/status/status_manifest-e7416fcfeedbe261454d619d119599335f4c7b18c9e245c13722dbb0998dc023.css" media="all" />
63
64    
64<script src="https://dka575ofm4ao0.cloudfront.net/assets/jquery-3.5.1.min-729e416557a365062a8a20f0562f18aa171da57298005d392312670c706c68de.js"></script>
64
65
66    
66<script>
67      window.pageColorData = {"blue":"#0068FF","border":"#CCE1FF","body_background":"#fff","font":"#333333","graph":"#0068FF","green":"#05c47a","light_font":"#8794A0","link":"#0068FF","orange":"#FF8C3E","red":"#FF5050","yellow":"#efcc00","no_data":"#b3bac5"};
68    </script>
68
69    <style>
70  /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */
71  body,
72  .layout-content.status.status-api .section .example-container .example-opener .color-secondary,
73  .grouped-items-selector,
74  .layout-content.status.status-full-history .history-nav a.current,
75  div[id^="subscribe-modal"] .modal-footer,
76  div[id^="subscribe-modal"],
77  div[id^="updates-dropdown"] .updates-dropdown-section,
78  #uptime-tooltip .tooltip-box {
79    background-color:#fff;
80  }
81
82  #uptime-tooltip .pointer-container .pointer-smaller {
83    border-bottom-color:#fff;
84  }
85
86
87
88
89  /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */
90  body.status,
91  .color-primary,
92  .color-primary:hover,
93  .layout-content.status-index .status-day .update-title.impact-none a,
94  .layout-content.status-index .status-day .update-title.impact-none a:hover,
95  .layout-content.status-index .timeframes-container .timeframe.active,
96  .layout-content.status-full-history .month .incident-container .impact-none,
97  .layout-content.status.status-index .incidents-list .incident-title.impact-none a,
98  .incident-history .impact-none,
99  .layout-content.status .grouped-items-selector.inline .grouped-item.active,
100  .layout-content.status.status-full-history .history-nav a.current,
101  .layout-content.status.status-full-history .history-nav a:not(.current):hover,
102  div[id^="subscribe-modal"] .modal-header .close,
103  .grouped-item-label,
104  #uptime-tooltip .tooltip-box .tooltip-content .related-events .related-event a.related-event-link {
105    color:#333333;
106  }
107
108  .layout-content.status.status-index .components-statuses .component-container .name {
109    color:#333333;
110    color:rgba(51,51,51,.8);
111  }
112
113
114
115
116  /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */
117  small,
118  .layout-content.status .table-row .date,
119  .color-secondary,
120  .layout-content.status .grouped-items-selector.inline .grouped-item,
121  .layout-content.status.status-full-history .history-footer .pagination a.disabled,
122  .layout-content.status.status-full-history .history-nav a,
123  #uptime-tooltip .tooltip-box .tooltip-content .related-events #related-event-header {
124    color:#8794A0;
125  }
126
127
128
129
130  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */
131  body.status .layout-content.status .border-color,
132  hr,
133  .tooltip-base,
134  .markdown-display table,
135  div[id^="subscribe-modal"],
136  #uptime-tooltip .tooltip-box {
137    border-color:#CCE1FF;
138  }
139
140  div[id^="subscribe-modal"] .modal-footer,
141  .markdown-display table td {
142    border-top-color:#CCE1FF;
143  }
144
145  .markdown-display table td + td, .markdown-display table th + th {
146    border-left-color:#CCE1FF;
147  }
148
149  div[id^="subscribe-modal"] .modal-header,
150  #uptime-tooltip .pointer-container .pointer-larger {
151    border-bottom-color:#CCE1FF;
152  }
153
154  #uptime-tooltip .tooltip-box .outage-field {
155    /*
156      Generate the background-color for the outage-field from the css_body_background_color and css_border_color.
157
158      For the default background (#ffffff) and default css_border_color (#e0e0e0), use the luminosity of the default background with a magic number to arrive at
159      the original outage-field background color (#f4f5f7). I used the formula Target Color = Color * alpha + Background * (1 - alpha) to find the magic number of ~0.08.
160
161      For darker css_body_background_color, luminosity values are lower so alpha trends toward becoming transparent (thus outage-field background becomes same as css_body_background_color).
162    */
163    background-color: rgba(204,225,255,0.31);
164
165    /*
166      outage-field border-color alpha is inverse to the luminosity of css_body_background_color.
167      That is to say, with a default white background this border is transparent, but on a black background, it's opaque css_border_color.
168    */
169    border-color: rgba(204,225,255,0.0);
170  }
171
172
173
174
175  /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */
176  .layout-content.status.status-index .status-day .update-title.impact-critical a,
177  .layout-content.status.status-index .status-day .update-title.impact-critical a:hover,
178  .layout-content.status.status-index .page-status.status-critical,
179  .layout-content.status.status-index .unresolved-incident.impact-critical .incident-title,
180  .flat-button.background-red {
181    background-color:#FF5050;
182  }
183
184  .layout-content.status-index .components-statuses .component-container.status-red:after,
185  .layout-content.status-full-history .month .incident-container .impact-critical,
186  .layout-content.status-incident .incident-name.impact-critical,
187  .layout-content.status.status-index .incidents-list .incident-title.impact-critical a,
188  .status-red .icon-indicator,
189  .incident-history .impact-critical,
190  .components-container .component-inner-container.status-red .component-status,
191  .components-container .component-inner-container.status-red .icon-indicator {
192    color:#FF5050;
193  }
194
195  .layout-content.status.status-index .unresolved-incident.impact-critical .updates {
196    border-color:#FF5050;
197  }
198
199
200
201
202  /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */
203  .layout-content.status.status-index .status-day .update-title.impact-major a,
204  .layout-content.status.status-index .status-day .update-title.impact-major a:hover,
205  .layout-content.status.status-index .page-status.status-major,
206  .layout-content.status.status-index .unresolved-incident.impact-major .incident-title {
207    background-color:#FF8C3E;
208  }
209
210  .layout-content.status-index .components-statuses .component-container.status-orange:after,
211  .layout-content.status-full-history .month .incident-container .impact-major,
212  .layout-content.status-incident .incident-name.impact-major,
213  .layout-content.status.status-index .incidents-list .incident-title.impact-major a,
214  .status-orange .icon-indicator,
215  .incident-history .impact-major,
216  .components-container .component-inner-container.status-orange .component-status,
217  .components-container .component-inner-container.status-orange .icon-indicator {
218    color:#FF8C3E;
219  }
220
221  .layout-content.status.status-index .unresolved-incident.impact-major .updates {
222    border-color:#FF8C3E;
223  }
224
225
226
227
228  /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */
229  .layout-content.status.status-index .status-day .update-title.impact-minor a,
230  .layout-content.status.status-index .status-day .update-title.impact-minor a:hover,
231  .layout-content.status.status-index .page-status.status-minor,
232  .layout-content.status.status-index .unresolved-incident.impact-minor .incident-title,
233  .layout-content.status.status-index .scheduled-incidents-container .tab {
234    background-color:#efcc00;
235  }
236
237  .layout-content.status-index .components-statuses .component-container.status-yellow:after,
238  .layout-content.status-full-history .month .incident-container .impact-minor,
239  .layout-content.status-incident .incident-name.impact-minor,
240  .layout-content.status.status-index .incidents-list .incident-title.impact-minor a,
241  .status-yellow .icon-indicator,
242  .incident-history .impact-minor,
243  .components-container .component-inner-container.status-yellow .component-status,
244  .components-container .component-inner-container.status-yellow .icon-indicator,
245  .layout-content.status.manage-subscriptions .confirmation-infobox .fa {
246    color:#efcc00;
247  }
248
249  .layout-content.status.status-index .unresolved-incident.impact-minor .updates,
250  .layout-content.status.status-index .scheduled-incidents-container {
251    border-color:#efcc00;
252  }
253
254
255
256
257  /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */
258  .layout-content.status.status-index .status-day .update-title.impact-maintenance a,
259  .layout-content.status.status-index .status-day .update-title.impact-maintenance a:hover,
260  .layout-content.status.status-index .page-status.status-maintenance,
261  .layout-content.status.status-index .unresolved-incident.impact-maintenance .incident-title,
262  .layout-content.status.status-index .scheduled-incidents-container .tab {
263    background-color:#0068FF;
264  }
265
266  .layout-content.status-index .components-statuses .component-container.status-blue:after,
267  .layout-content.status-full-history .month .incident-container .impact-maintenance,
268  .layout-content.status-incident .incident-name.impact-maintenance,
269  .layout-content.status.status-index .incidents-list .incident-title.impact-maintenance a,
270  .status-blue .icon-indicator,
271  .incident-history .impact-maintenance,
272  .components-container .component-inner-container.status-blue .component-status,
273  .components-container .component-inner-container.status-blue .icon-indicator {
274    color:#0068FF;
275  }
276
277  .layout-content.status.status-index .unresolved-incident.impact-maintenance .updates,
278  .layout-content.status.status-index .scheduled-incidents-container {
279    border-color:#0068FF;
280  }
281
282
283
284
285  /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */
286  .layout-content.status.status-index .page-status.status-none {
287    background-color:#05c47a;
288  }
289  .layout-content.status-index .components-statuses .component-container.status-green:after,
290  .status-green .icon-indicator,
291  .components-container .component-inner-container.status-green .component-status,
292  .components-container .component-inner-container.status-green .icon-indicator {
293    color:#05c47a;
294  }
295
296
297
298
299  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */
300  a,
301  a:hover,
302  .layout-content.status-index .page-footer span a:hover,
303  .layout-content.status-index .timeframes-container .timeframe:not(.active):hover,
304  .layout-content.status-incident .subheader a:hover {
305    color:#0068FF;
306  }
307
308  .flat-button,
309  .masthead .updates-dropdown-container .show-updates-dropdown,
310  .layout-content.status-full-history .show-filter.open  {
311    background-color:#0068FF;
312  }
313
314
315
316
317  /* CUSTOM COLOR OVERRIDES FOR UPTIME SHOWCASE */
318  .components-section .components-uptime-link {
319    color: #8794a0;
320  }
321
322  .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item {
323    color: #8794a0;
324    opacity: 1;
325  }
326  .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item.light {
327    color: #8794a0;
328    opacity: 1;
329  }
330  .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .spacer {
331    background: #8794a0;
332    opacity: 1;
333  }
334</style>
335
336
337    <!-- custom css -->
338
339      <!-- polyfills -->
340        
340<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js"></script>
340
341
342    <!-- Le HTML5 shim -->
343    <!--[if lt IE 9]>
344      
344<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
344
345    <![endif]-->
346
347    <!-- injection for static -->
348
349
350    
351  </head>
352
353
354  <body class="status index status-none sp-a11y-status-focus-visibility a11y-focus-indicators">
355
356    
357
358
359
360  <div class="layout-content status status-index premium">
361      <div class="masthead-container premium">
362    <div class="masthead">
363      <div class="images-container" id="cover-image-container" data-js-hook="images-container"></div>
364      <style>
365          #cover-image-container {
366            background-image:url("//dka575ofm4ao0.cloudfront.net/pages-hero_covers/normal/27/tci-logo_w1700h630-e25efd0e-8bda-4e6f-b5ca-e6ba7eb2ab65.png");
367          }
368
369          @media only screen and (-webkit-min-device-pixel-ratio: 2),
370                 only screen and (min-resolution: 192dpi) {
371            #cover-image-container {
372              background-image:url("//dka575ofm4ao0.cloudfront.net/pages-hero_covers/retina/27/tci-logo_w1700h630-e25efd0e-8bda-4e6f-b5ca-e6ba7eb2ab65.png") !important;
373            }
374          }
375      </style>
376
377      <div class="text-container">
378        <span class="page-name font-largest">
379            <a href="https://travis-ci.com">Travis CI</a>
380        </span>
381          
382  <div class="updates-dropdown-container" data-js-hook="updates-dropdown-container">
383    <a href="#" data-js-hook="show-updates-dropdown" id="show-updates-dropdown" class="show-updates-dropdown" aria-label="Subscribe to updates" aria-expanded="false" aria-haspopup="dialog" role="button">
384      <span class="subscribe-text-full">Subscribe to Updates</span><span class="subscribe-text-short">Subscribe</span>
385    </a>
386
387<!--    Accessibility guidelines for tabs: https://www.w3.org/TR/wai-aria-practices-1.1/examples/tabs/tabs-1/tabs.html -->
388    <div class="updates-dropdown" data-js-hook="updates-dropdown" id="updates-dropdown" style="display:none" role="dialog" aria-modal="false" aria-label="Subscribe to updates">
389      <div class="updates-dropdown-nav nav-items-5" role="tablist" aria-label="Subscribe to updates">
390          <a href="#updates-dropdown-email" aria-controls="updates-dropdown-email" aria-label="Subscribe via email" role="tab" aria-selected="true" id="updates-dropdown-email-btn">
391            <span class="icon-container email">
392          </a>
393          <a href="#updates-dropdown-slack" aria-controls="updates-dropdown-slack" aria-label="Subscribe via slack" role="tab" id="updates-dropdown-slack-btn">
394            <span class="icon-container slack">
395          </a>
396          <a href="#updates-dropdown-webhook" aria-controls="updates-dropdown-webhook" aria-label="Subscribe via webhook" role="tab" id="updates-dropdown-webhook-btn">
397            <span class="icon-container webhook">
398          </a>
399          <a href="#updates-dropdown-atom" aria-controls="updates-dropdown-atom" aria-label="Subscribe via RSS" role="tab" id="updates-dropdown-atom-btn">
400            <span class="icon-container rss">
401          </a>
402        <button data-js-hook="updates-dropdown-close" aria-label="Close subscribe form" id="updates-dropdown-close-btn">
403          x
404        </button>
405      </div>
406      <div class="updates-dropdown-sections-container">
407          <div class="updates-dropdown-section email" id="updates-dropdown-email" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-email-btn">
408            <div class="directions">
409              Get email notifications whenever Travis CI <strong>creates</strong>,  <strong>updates</strong> or <strong>resolves</strong> an incident.
410            </div>
411            <form id="subscribe-form-email" action="/subscriptions/new-email" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="KIFt4sQMO2UFlo2YiTGxgG1pEvNxGH1ZNCXufVIXNrSFUZ4xKG_PkIhB4OFpVe5sOaH02c4rdUVMpweU1L29yQ" autocomplete="off" />
412              <input type="hidden" name="email_otp_verify_flow" id="email_otp_verify_flow" value="false" autocomplete="off" />
413                <!-- make sure not to put cookie values in here since this gets cached -->
414                <label for="email">Email address:</label>
415                <input name="email" id="email" type="text" class="full-width" data-js-hook="email-notification-field" autocomplete="email">
416                <input name="email_otp_auth_token" type='hidden' id="email-
416otp-token-field">
417                <div class="opt-container-section" id="email-otp-container", style="display:none" >
418                  <label for="email-otp">Enter OTP:</label>
419                  <input name="otp" id="email-otp" type="text" value="" class="prepend full-width">
420                  <p id="email-otp-timer">Resend OTP in: <span id="email-otp-countdown"></span> seconds </p>
421                  <p id="resend-email-otp">
422                    Didn't receive the OTP?
423                    <a href="#" id="resend-email-otp-btn" >Resend OTP </a>
424                  </p>
425                </div>
426                  <input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" />
427                  <input type="submit" value="Subscribe via Email" class="flat-button full-width g-recaptcha" id="subscribe-btn-email" data-disabled-text="Subscribing..." data-sitekey=6LdTS8AUAAAAAOIbCKoCAP4LQku1olYGrywPTaZz data-callback="submitNewEmailSubscriber" data-error-callback="emailSubscriberCaptchaError" >
428                  <div class="terms_and_privacy_information bottom small"><div class="privacy_policy_information small">By subscribing you agree to our <a target="_blank" rel="noopener" class="accessible-link" href="https://www.ideracorp.com/Legal/PrivacyPolicy">Privacy Policy</a>.</div> This site is protected by reCAPTCHA and the Google <a target="_blank" rel="noopener" class="accessible-link" href="https://policies.google.com/privacy">Privacy Policy</a> and <a target="_blank" rel="noopener" class="accessible-link" data-js-hook="captcha-terms-of-service-link" href="https://policies.google.com/terms">Terms of Service</a> apply.</div>
429</form>          </div>
430
431
432          <div class="updates-dropdown-section slack" id="updates-dropdown-slack" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-slack-btn">
433            <div class="directions">
434              Get incident updates and maintenance status messages in Slack.
435            </div>
436            <a value="Subscribe via Slack" class="flat-button full-width" id="subscribe-btn-slack" data-disabled-text="Subscribing..." data-revert-on-success="true" style="margin-top:.75rem" href="https://subscriptions.statuspage.io/slack_authentication/kickoff?page_code=pnpcptp8xh9k">Subscribe via Slack</a>
437            <div class="terms_and_privacy_information bottom small">By subscribing you acknowledge our <a target="_blank" rel="noopener" class="accessible-link" href="https://www.ideracorp.com/Legal/PrivacyPolicy">Privacy Policy</a>. In addition, you agree to the Atlassian <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/cloud-terms-of-service">Cloud Terms of Service</a> and acknowledge Atlassian's <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/privacy-policy">Privacy Policy</a>.</div>
438          </div>
439
440
441          <div class="updates-dropdown-section webhook" id="updates-dropdown-webhook" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-webhook-btn">
442            <div class="directions">
443              Get webhook notifications whenever Travis CI <strong>creates</strong> an incident, <strong>updates</strong> an incident, <strong>resolves</strong> an incident or <strong>changes</strong> a component status.
444            </div>
445            <form id="subscribe-form-webhook" action="/subscriptions/webhook.json" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="y_FQIFPdzXjt4mFyTyqWsjgXDvIJ_SHF0G088Jzq5bFmIaPzv745jWA1DAuvTslebN_o2LbOKdmo79UZGkBuzA" autocomplete="off" />
446              <div class="control-group">
447                <div class="controls">
448                  <label for="endpoint-webhooks">Webhook URL:</label>
449                  <input type="text" name="endpoint" id="endpoint-webhooks" data-js-hook="endpoint" class="full-width" aria-describedby="url-help-block" />
450                  <p class="help-block" id="url-help-block">The URL we should send the webhooks to</p>
451                </div>
452              </div>
453
454              <div class="control-group">
455                <div class="controls">
456                  <label for="email-webhooks">Email address:</label>
457                  <input type="text" name="email" id="email-webhooks" data-js-hook="email" class="full-width" aria-describedby="email-help-block" />
458                  <p class="help-block" id="email-help-block">We'll send you email if your endpoint fails</p>
459                </div>
460              </div>
461
462                <input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" />
463                <input type="submit" value=Subscribe To Notifications class="flat-button full-width g-recaptcha" id="subscribe-btn-webhook" data-disabled-text="Subscribing..." data-sitekey=6LcQ-b0UAAAAAJjfdwO_-ozGC-CzWDj4Pm1kJ2Ah data-callback="submitNewWebhookSubscriber" data-error-callback="webhookSubscriberCaptchaError">
464                <div class="terms_and_privacy_information bottom small"><div class="privacy_policy_information small">By subscribing you agree to our <a target="_blank" rel="noopener" class="accessible-link" href="https://www.ideracorp.com/Legal/PrivacyPolicy">Privacy Policy</a>.</div> This site is protected by reCAPTCHA and the Google <a target="_blank" rel="noopener" class="accessible-link" href="https://policies.google.com/privacy">Privacy Policy</a> and <a target="_blank" rel="noopener" class="accessible-link" data-js-hook="captcha-terms-of-service-link" href="https://policies.google.com/terms">Terms of Service</a> apply.</div>
465
466</form>          </div>
467
468
469
470          <div class="updates-dropdown-section atom" id="updates-dropdown-atom" role="tabpanel" aria-labelledby="updates-dropdown-atom-btn">
471            Get the <a href="https://www.traviscistatus.com/history.atom" target="_blank">Atom Feed</a> or <a href="https://www.traviscistatus.com/history.rss" target="_blank">RSS Feed</a>.
472          </div>
473      </div>
474    </div>
475  </div>
476
477<script>
478  $(function () {
479    const phoneNumberInput = $('#phone-number');
480    const errorDiv = $('#sms-atl-error')
481    if(errorDiv.length){
482      function checkSelectedCountry() {
483        const selectedCountry = $('#phone-country').val();
484        const isOtpEnabled = $('#phone-number-country-code').attr('data-otp-enabled') === 'true';
485        const form = document.getElementById('subscribe-form-sms');
486        form.action = '/subscriptions/new-sms';
487        const isOtpFlow = document.getElementById('otp_verify_flow');
488        document.getElementById('otp-container').style.display = "none";
489        if(false && selectedCountry === 'sg') { // Replace 'SG' with the actual value representing Singapore in your select tag
490          phoneNumberInput.prop('disabled', true);
491          errorDiv.html(`Due to new Singapore government regulations, we're currently not supporting text subscriptions in Singapore.<a href="https://community.atlassian.com/t5/Statuspage-articles/Attention-SMS-notifications-will-be-disabled-on-August-1st-2023/ba-p/2424398" target="_blank"> Learn more.</a> <br> Select another method to subscribe.`);
492        } else {
493          phoneNumberInput.prop('readonly', false);
494          errorDiv.html('');
495          if(false){
496            if(isOtpEnabled){
497              document.getElementById('subscribe-btn-sms').value = "Send OTP";
498            }
499            else {
500              isOtpFlow.value = false;
501              document.getElementById('subscribe-btn-sms').value = "Subscribe via Text Message";
502            }
503          }
504        }
505      }
506
507      $('#phone-country').on('change', checkSelectedCountry);
508      checkSelectedCountry();
509    }
510  });
511
512  document.addEventListener('DOMContentLoaded', function() {
513    const dropdown = document.querySelector('#phone-number-country-code .phone-country');
514    if (dropdown){
515      const wrapperDiv = document.getElementById('phone-number-country-code');
516      const selectedOption = dropdown.options[dropdown.selectedIndex];
517      const otpEnabled = selectedOption.getAttribute('data-otp-enabled');
518
519      wrapperDiv.setAttribute('data-otp-enabled', otpEnabled);
520
521      dropdown.addEventListener('change', function() {
522        const selectedOption = dropdown.options[dropdown.selectedIndex];
523        const otpEnabled = selectedOption.getAttribute('data-otp-enabled');
524
525        wrapperDiv.setAttribute('data-otp-enabled', otpEnabled);
526      });
527    }
528  });
529
530  var countdownTimer;
531  var resendBtn = document.getElementById('resend');
532  var timer = document.getElementById('timer');
533  var form = document.getElementById('subscribe-form-sms');
534  var RESEND_TIMER = 30;
535  $(function() {
536    $('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){
537      const form = this;
538      const action = form.getAttribute('action');
539      if (data.type === 'success' && data.otp_flow === true) {
540        document.getElementById('subscriber_code').value = data.subscriber_code
541        document.getElementById('otp-container').style.display = "block";
542        $('#phone-number').prop('readonly', true);
543        var display = document.getElementById('countdown');
544        disableResend();
545        startTimer(RESEND_TIMER, display)
546        document.getElementById('subscribe-btn-sms').value = "Verify OTP and Subscribe";
547        document.getElementById('otp_verify_flow').value = true;
548        form.action = '/subscriptions/verify-otp';
549      } else if (data.type === 'success' && action.includes('verify')){
550        document.getElementById('otp-container').style.display = "none";
551        $('#phone-number').val('').prop('readonly', false);
552        $('#otp').val('');
553        document.getElementById('subscribe-btn-sms').value = "Send OTP";
554        document.getElementById('otp_verify_flow').value = false;
555        form.action = '/subscriptions/new-sms';
556        SP.currentPage.updatesDropdown.hide();
557      }
558    });
559    $("#btn-subcriber-change-number").on('click', () => {
560      document.getElementById('otp-container').style.display = "none";
561      $('#phone-number').prop('readonly', false);
562      document.getElementById('subscribe-btn-sms').value = "Send OTP";
563      form.action = '/subscriptions/new-sms';
564      return false
565    })
566    $('#resend-otp-btn').on('click', function(e) {
567      e.preventDefault();
568      let phoneNumber = $('#phone-number').val();
569      let countryCode = $('.phone-country').val();
570      $.ajax({
571        type: 'POST',
572        url: "/subscriptions/new-sms",
573        data: {
574          phone_number: phoneNumber,
575          phone_country: countryCode,
576          type: 'resend'
577        },
578      }).done(function(data) {
579        var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {};
580        HRB.utils.notify(data.text, messageOptions);
581        var display = document.getElementById('countdown');
582        disableResend();
583        timer.style.display = "none"
584        if (data.type === 'success') {
585          startTimer(RESEND_TIMER, display);
586        }
587      })
588    });
589  })
590
591  function startTimer(duration, display){
592    var timer = duration, seconds;
593    clearInterval(countdownTimer);
594    countdownTimer = setInterval(function () {
595      seconds = parseInt(timer % 60, 10);
596      display.textContent = seconds;
597      if(--timer < 0){
598        enableResend();
599        clearInterval(countdownTimer);
600      }
601    }, 1000);
602    disableResend();
603  }
604  function enableResend(){
605    resendBtn.style.display = "block";
606    timer.style.display = "none"
607  }
608  function disableResend(){
609    resendBtn.style.display = "none";
610    timer.style.display = "block"
611  }
612
613  $(function() {
614    $('#subscribe-form-email').on('submit', function() {
615      var tokenField = document.getElementById('email-otp-token-field');
616      if (!tokenField) {
617        return;
618      }
619      let page_code = "pnpcptp8xh9k"
620      let key = keyForEmailOtpToken($('#email').val(), page_code);
621      tokenField.value = localStorage.getItem(key);
622    });
623  });
624
625  var emailOtpCountdownTimer;
626  var emailOtpResendBtn = document.getElementById('resend-email-otp');
627  var emailOtpTimer = document.getElementById('email-otp-timer');
628  var emailOtpForm = document.getElementById('subscribe-form-email');
629  var EMAIL_OTP_RESEND_TIMER = 600;
630  $(function() {
631    $('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){
632      const form = this;
633      const action = form.getAttribute('action');
634      if (data.type === 'success' && data.email_otp_verify_flow === true) {
635        document.getElementById('email-otp-container').style.display = "block";
636        var display = document.getElementById('email-otp-countdown');
637        display.textContent = EMAIL_OTP_RESEND_TIMER;
638        disableEmailOtpResend();
639        startEmailOtpTimer(EMAIL_OTP_RESEND_TIMER, display)
640        document.getElementById('subscribe-btn-email').value = "Verify OTP and Subscribe";
641        document.getElementById('email_otp_verify_flow').value = true;
642        form.action = '/subscriptions/verify-email-otp';
643      } else if (data.type === 'success' && action.includes('verify')){
644        let email =  $('#email')
645        let page_code = "pnpcptp8xh9k"
646        let key = keyForEmailOtpToken(email.val(), page_code);
647        localStorage.setItem(key, data.email_otp_auth_token);
648
649        document.getElementById('email-otp-container').style.display = "none";
650        email.val('').prop('readonly', false);
651        $('#email-otp').val('');
652        document.getElementById('subscribe-btn-email').value = "Send OTP";
653        document.getElementById('email_otp_verify_flow').value = false;
654        form.action = '/subscriptions/new-email';
655        SP.currentPage.updatesDropdown.hide();
656      }
657    });
658    $('#resend-email-otp-btn').on('click', function(e) {
659      e.preventDefault();
660      let email = $('#email').val();
661      $.ajax({
662        type: 'POST',
663        url: "/subscriptions/new-email",
664        data: {
665          email: email
666        },
667      }).done(function(data) {
668        var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {};
669        HRB.utils.notify(data.text, messageOptions);
670        if (data.type === 'success') {
671          var display = document.getElementById('email-otp-countdown');
672          display.textContent = EMAIL_OTP_RESEND_TIMER;
673          disableEmailOtpResend();
674          emailOtpTimer.style.display = "none"
675          startEmailOtpTimer(EMAIL_OTP_RESEND_TIMER, display);
676        }
677      })
678    });
679  })
680
681  function startEmailOtpTimer(duration, display){
682    var timer = duration, seconds;
683    clearInterval(emailOtpCountdownTimer);
684    emailOtpCountdownTimer = setInterval(function () {
685      seconds = parseInt(timer, 10);
686      display.textContent = seconds;
687      if(--timer < 0){
688        enableEmailOtpResend();
689        clearInterval(emailOtpCountdownTimer);
690      }
691    }, 1000);
692    disableEmailOtpResend();
693  }
694
695  function enableEmailOtpResend(){
696    emailOtpResendBtn.style.display = "block";
697    emailOtpTimer.style.display = "none"
698  }
699  function disableEmailOtpResend(){
700    emailOtpResendBtn.style.display = "none";
701    emailOtpTimer.style.display = "block"
702  }
703  function keyForEmailOtpToken(email, pageCode) {
704    return email + '|' + pageCode+ '|SUBSCRIBE_VIA_EMAIL';
705  }
706</script>
706
707
708      </div>
709    </div>
710
711</div>
712 <!-- this is outside of the .container so that the cover photo can go full width on mobile -->
713
714    <div class="container" role="main">
715        <div class="page-status status-none">
716          <h2 class="status font-large">
717            All Systems Operational
718          </h2>
719          <span class="last-updated-stamp  font-small"></span>
720        </div>
721
722
723
724        <div class="components-section font-regular">
725      <i class="component-status hidden major_outage"></i>
726      <div class="components-uptime-link history-footer-link">
727        Uptime over the past <var data-var="num" data-pluralize="90">90</var> days. <a href="/uptime">View historical uptime.</a>
728      </div>
729    <div class="components-container one-column">
730          <div class="component-container border-color">
731            
732<div data-component-id="v3pv505czcvn"
733     class="component-inner-container status-green showcased"
734     data-component-status="operational"
735     data-js-hook="">
736
737   <span class="name" role="heading" aria-level="2">
738      API
739   </span>
740
741
742  <span
743    class="component-status "
744    
745    title=""
746  >
747
748    Operational
749
750  </span>
751
752  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
753
754    <div class="uptime-lazy-placeholder" data-uptime-lazy="v3pv505czcvn" aria-hidden="true"></div>
755</div>
756
757          </div>
758          <div class="component-container border-color">
759            
760<div data-component-id="x0lpb7qzw919"
761     class="component-inner-container status-green showcased"
762     data-component-status="operational"
763     data-js-hook="">
764
765   <span class="name" role="heading" aria-level="2">
766      Web App
767   </span>
768
769
770  <span
771    class="component-status "
772    
773    title=""
774  >
775
776    Operational
777
778  </span>
779
780  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
781
782    <div class="uptime-lazy-placeholder" data-uptime-lazy="x0lpb7qzw919" aria-hidden="true"></div>
783</div>
784
785          </div>
786          <div class="component-container border-color is-group ">
787  
788<div data-component-id="zd1jfc33yt1p"
789     class="component-inner-container status-green showcased"
790     data-component-status="operational"
791     data-js-hook="component-group-opener">
792
793   <span class="name" role="heading" aria-level="2">
794       <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Builds Processing" tabindex="0"></span>
795       <span>
796         Builds Processing
797       </span>
798   </span>
799
800
801  <span
802    class="component-status "
803    role="button" tabindex="0" data-js-hook="tooltip"
804    data-original-title="Groups take on the status of their most degraded child component or service. Click to see the status of the individual children."
805  >
806
807    Operational
808
809  </span>
810
811  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
812
813    <div class="uptime-lazy-placeholder" data-uptime-lazy="zd1jfc33yt1p" aria-hidden="true"></div>
814</div>
815
816
817  <!-- children components -->
818  <div class="child-components-container mix-match-showcase">
819      
820<div data-component-id="fv408yjjqhv6"
821     class="component-inner-container status-green showcased"
822     data-component-status="operational"
823     data-js-hook="">
824
825   <span class="name" role="heading" aria-level="2">
826      Linux and Windows Builds
827   </span>
828
829    <button
830      type="button"
831      class="tooltip-base tool"
832      data-js-hook="tooltip"
833      tabindex="0"
834      aria-label="More information about Linux and Windows Builds"
835      aria-describedby="tooltip-fv408yjjqhv6"
836      data-original-title="VM builds running in GCE. This includes both Linux (all distributions) and Windows builds."
837    >?</button>
838
839  <span
840    class="component-status "
841    
842    title=""
843  >
844
845    Operational
846
847  </span>
848
849  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
850
851    <div class="uptime-lazy-placeholder" data-uptime-lazy="fv408yjjqhv6" aria-hidden="true"></div>
852</div>
853
854      
855<div data-component-id="5wvsvvr8b7j4"
856     class="component-inner-container status-green "
857     data-component-status="operational"
858     data-js-hook="">
859
860   <span class="name" role="heading" aria-level="2">
861      IBM Z Builds
862   </span>
863
864    <button
865      type="button"
866      class="tooltip-base tool"
867      data-js-hook="tooltip"
868      tabindex="0"
869      aria-label="More information about IBM Z Builds"
870      aria-describedby="tooltip-5wvsvvr8b7j4"
871      data-original-title="Scheduling and running of builds on the IBM s390x architecture."
872    >?</button>
873
874  <span
875    class="component-status "
876    
877    title=""
878  >
879
880    Operational
881
882  </span>
883
884  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
885
886</div>
887
888  </div>
889</div>
890
891          <div class="component-container border-color is-group ">
892  
893<div data-component-id="43255b952p01"
894     class="component-inner-container status-green showcased"
895     data-component-status="operational"
896     data-js-hook="component-group-opener">
897
898   <span class="name" role="heading" aria-level="2">
899       <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Background Processing" tabindex="0"></span>
900       <span>
901         Background Processing
902       </span>
903   </span>
904
905
906  <span
907    class="component-status "
908    role="button" tabindex="0" data-js-hook="tooltip"
909    data-original-title="Groups take on the status of their most degraded child component or service. Click to see the status of the individual children."
910  >
911
912    Operational
913
914  </span>
915
916  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
917
918    <div class="uptime-lazy-placeholder" data-uptime-lazy="43255b952p01" aria-hidden="true"></div>
919</div>
920
921
922  <!-- children components -->
923  <div class="child-components-container ">
924      
925<div data-component-id="pw8ss5jcjb45"
926     class="component-inner-container status-green showcased"
927     data-component-status="operational"
928     data-js-hook="">
929
930   <span class="name" role="heading" aria-level="2">
931      Log Processing
932   </span>
933
934
935  <span
936    class="component-status "
937    
938    title=""
939  >
940
941    Operational
942
943  </span>
944
945  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
946
947    <div class="uptime-lazy-placeholder" data-uptime-lazy="pw8ss5jcjb45" aria-hidden="true"></div>
948</div>
949
950      
951<div data-component-id="vmgk8phkxfdf"
952     class="component-inner-container status-green showcased"
953     data-component-status="operational"
954     data-js-hook="">
955
956   <span class="name" role="heading" aria-level="2">
957      User Sync
958   </span>
959
960    <button
961      type="button"
962      class="tooltip-base tool"
963      data-js-hook="tooltip"
964      tabindex="0"
965      aria-label="More information about User Sync"
966      aria-describedby="tooltip-vmgk8phkxfdf"
967      data-original-title="Synchronization with GitHub / Assembla / GitLab / BitBucket via their API"
968    >?</button>
969
970  <span
971    class="component-status "
972    
973    title=""
974  >
975
976    Operational
977
978  </span>
979
980  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
981
982    <div class="uptime-lazy-placeholder" data-uptime-lazy="vmgk8phkxfdf" aria-hidden="true"></div>
983</div>
984
985      
986<div data-component-id="y0v5kvk1msqy"
987     class="component-inner-container status-green showcased"
988     data-component-status="operational"
989     data-js-hook="">
990
991   <span class="name" role="heading" aria-level="2">
992      Notifications
993   </span>
994
995    <button
996      type="button"
997      class="tooltip-base tool"
998      data-js-hook="tooltip"
999      tabindex="0"
1000      aria-label="More information about Notifications"
1001      aria-describedby="tooltip-y0v5kvk1msqy"
1002      data-original-title="Build notifications like email, Campfire, Slack, HipChat, IRC"
1003    >?</button>
1004
1005  <span
1006    class="component-status "
1007    
1008    title=""
1009  >
1010
1011    Operational
1012
1013  </span>
1014
1015  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1016
1017    <div class="uptime-lazy-placeholder" data-uptime-lazy="y0v5kvk1msqy" aria-hidden="true"></div>
1018</div>
1019
1020  </div>
1021</div>
1022
1023          <div class="component-container border-color is-group ">
1024  
1025<div data-component-id="ygwn6k3272yn"
1026     class="component-inner-container status-green "
1027     data-component-status="operational"
1028     data-js-hook="component-group-opener">
1029
1030   <span class="name" role="heading" aria-level="2">
1031       <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Third Party Services" tabindex="0"></span>
1032       <span>
1033         Third Party Services
1034       </span>
1035   </span>
1036
1037
1038  <span
1039    class="component-status "
1040    role="button" tabindex="0" data-js-hook="tooltip"
1041    data-original-title="Groups take on the status of their most degraded child component or service. Click to see the status of the individual children."
1042  >
1043
1044    Operational
1045
1046  </span>
1047
1048  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1049
1050</div>
1051
1052
1053  <!-- children components -->
1054  <div class="child-components-container ">
1055      
1056<div data-component-id="kgbljfbx7598"
1057     class="component-inner-container status-green "
1058     data-component-status="operational"
1059     data-js-hook="">
1060
1061   <span class="name" role="heading" aria-level="2">
1062      GitHub
1063   </span>
1064
1065
1066  <span
1067    class="component-status "
1068    
1069    title=""
1070  >
1071
1072    Operational
1073
1074  </span>
1075
1076  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1077
1078</div>
1079
1080      
1081<div data-component-id="xgcz8vf731tx"
1082     class="component-inner-container status-green "
1083     data-component-status="operational"
1084     data-js-hook="">
1085
1086   <span class="name" role="heading" aria-level="2">
1087      DNSimple Name Servers
1088   </span>
1089
1090
1091  <span
1092    class="component-status "
1093    
1094    title=""
1095  >
1096
1097    Operational
1098
1099  </span>
1100
1101  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1102
1103</div>
1104
1105      
1106<div data-component-id="032hr7t0bg9b"
1107     class="component-inner-container status-green "
1108     data-component-status="operational"
1109     data-js-hook="">
1110
1111   <span class="name" role="heading" aria-level="2">
1112      Pusher Pusher REST API
1113   </span>
1114
1115
1116  <span
1117    class="component-status "
1118    
1119    title=""
1120  >
1121
1122    Operational
1123
1124  </span>
1125
1126  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1127
1128</div>
1129
1130      
1131<div data-component-id="t3ncs9kc9w2x"
1132     class="component-inner-container status-green "
1133     data-component-status="operational"
1134     data-js-hook="">
1135
1136   <span class="name" role="heading" aria-level="2">
1137      Pusher WebSocket client API
1138   </span>
1139
1140
1141  <span
1142    class="component-status "
1143    
1144    title=""
1145  >
1146
1147    Operational
1148
1149  </span>
1150
1151  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1152
1153</div>
1154
1155      
1156<div data-component-id="qblbn1tf2q02"
1157     class="component-inner-container status-green "
1158     data-component-status="operational"
1159     data-js-hook="">
1160
1161   <span class="name" role="heading" aria-level="2">
1162      Pusher Presence channels
1163   </span>
1164
1165
1166  <span
1167    class="component-status "
1168    
1169    title=""
1170  >
1171
1172    Operational
1173
1174  </span>
1175
1176  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1177
1178</div>
1179
1180      
1181<div data-component-id="lxczb8x45gmm"
1182     class="component-inner-container status-green "
1183     data-component-status="operational"
1184     data-js-hook="">
1185
1186   <span class="name" role="heading" aria-level="2">
1187      Pusher Webhooks
1188   </span>
1189
1190
1191  <span
1192    class="component-status "
1193    
1194    title=""
1195  >
1196
1197    Operational
1198
1199  </span>
1200
1201  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1202
1203</div>
1204
1205      
1206<div data-component-id="5vr9p1qt86l6"
1207     class="component-inner-container status-green "
1208     data-component-status="operational"
1209     data-js-hook="">
1210
1211   <span class="name" role="heading" aria-level="2">
1212      AWS ec2-us-east-1
1213   </span>
1214
1215
1216  <span
1217    class="component-status "
1218    
1219    title=""
1220  >
1221
1222    Operational
1223
1224  </span>
1225
1226  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1227
1228</div>
1229
1230      
1231<div data-component-id="wrxql47n0svb"
1232     class="component-inner-container status-green "
1233     data-component-status="operational"
1234     data-js-hook="">
1235
1236   <span class="name" role="heading" aria-level="2">
1237      PagerDuty Notification Delivery
1238   </span>
1239
1240
1241  <span
1242    class="component-status "
1243    
1244    title=""
1245  >
1246
1247    Operational
1248
1249  </span>
1250
1251  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1252
1253</div>
1254
1255      
1256<div data-component-id="k17399181mfn"
1257     class="component-inner-container status-green "
1258     data-component-status="operational"
1259     data-js-hook="">
1260
1261   <span class="name" role="heading" aria-level="2">
1262      npm, Inc. Registry Reads
1263   </span>
1264
1265    <button
1266      type="button"
1267      class="tooltip-base tool"
1268      data-js-hook="tooltip"
1269      tabindex="0"
1270      aria-label="More information about npm, Inc. Registry Reads"
1271      aria-describedby="tooltip-k17399181mfn"
1272      data-original-title="GETs to registry.npmjs.org"
1273    >?</button>
1274
1275  <span
1276    class="component-status "
1277    
1278    title=""
1279  >
1280
1281    Operational
1282
1283  </span>
1284
1285  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1286
1287</div>
1288
1289      
1290<div data-component-id="6p07pwzcl4wb"
1291     class="component-inner-container status-green "
1292     data-component-status="operational"
1293     data-js-hook="">
1294
1295   <span class="name" role="heading" aria-level="2">
1296      Assembla
1297   </span>
1298
1299    <button
1300      type="button"
1301      class="tooltip-base tool"
1302      data-js-hook="tooltip"
1303      tabindex="0"
1304      aria-label="More information about Assembla"
1305      aria-describedby="tooltip-6p07pwzcl4wb"
1306      data-original-title="Assembla.com Git, SVN and P4 repository and project management tool."
1307    >?</button>
1308
1309  <span
1310    class="component-status "
1311    
1312    title=""
1313  >
1314
1315    Operational
1316
1317  </span>
1318
1319  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1320
1321</div>
1322
1323  </div>
1324</div>
1325
1326          <div class="component-container border-color">
1327            
1328<div data-component-id="q4xyt8yypthv"
1329     class="component-inner-container status-green "
1330     data-component-status="operational"
1331     data-js-hook="">
1332
1333   <span class="name" role="heading" aria-level="2">
1334      Google Cloud Platform Google Compute Engine
1335   </span>
1336
1337
1338  <span
1339    class="component-status "
1340    
1341    title=""
1342  >
1343
1344    Operational
1345
1346  </span>
1347
1348  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1349
1350</div>
1351
1352          </div>
1353          <div class="component-container border-color">
1354            
1355<div data-component-id="xhp6ymqqyg3h"
1356     class="component-inner-container status-green "
1357     data-component-status="operational"
1358     data-js-hook="">
1359
1360   <span class="name" role="heading" aria-level="2">
1361      GitHub API Requests
1362   </span>
1363
1364
1365  <span
1366    class="component-status "
1367    
1368    title=""
1369  >
1370
1371    Operational
1372
1373  </span>
1374
1375  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1376
1377</div>
1378
1379          </div>
1380          <div class="component-container border-color">
1381            
1382<div data-component-id="c75kxzjv80rv"
1383     class="component-inner-container status-green "
1384     data-component-status="operational"
1385     data-js-hook="">
1386
1387   <span class="name" role="heading" aria-level="2">
1388      GitHub Issues, PRs, Dashboard, Projects
1389   </span>
1390
1391
1392  <span
1393    class="component-status "
1394    
1395    title=""
1396  >
1397
1398    Operational
1399
1400  </span>
1401
1402  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1403
1404</div>
1405
1406          </div>
1407          <div class="component-container border-color">
1408            
1409<div data-component-id="cs2n4vkyfmtk"
1410     class="component-inner-container status-green "
1411     data-component-status="operational"
1412     data-js-hook="">
1413
1414   <span class="name" role="heading" aria-level="2">
1415      Assembla API and Merge Requests
1416   </span>
1417
1418
1419  <span
1420    class="component-status "
1421    
1422    title=""
1423  >
1424
1425    Operational
1426
1427  </span>
1428
1429  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1430
1431</div>
1432
1433          </div>
1434          <div class="component-container border-color">
1435            
1436<div data-component-id="fhqxrfxvc50z"
1437     class="component-inner-container status-green "
1438     data-component-status="operational"
1439     data-js-hook="">
1440
1441   <span class="name" role="heading" aria-level="2">
1442      GitLab API and Pull Requests
1443   </span>
1444
1445
1446  <span
1447    class="component-status "
1448    
1449    title=""
1450  >
1451
1452    Operational
1453
1454  </span>
1455
1456  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1457
1458</div>
1459
1460          </div>
1461    </div>
1462    <div class="component-statuses-legend font-small">
1463  <div class="legend-item status-green">
1464    <span class="icon-indicator fa fa-check"></span>
1465    Operational
1466  </div>
1467  <div class="legend-item status-yellow">
1468    <span class="icon-indicator fa fa-minus-square"></span>
1469    Degraded Performance
1470  </div>
1471  <div class="legend-item status-orange">
1472    <span class="icon-indicator fa fa-exclamation-triangle"></span>
1473    Partial Outage
1474  </div>
1475  <div class="breaker"></div>
1476  <div class="legend-item status-red">
1477    <span class="icon-indicator fa fa-times"></span>
1478    Major Outage
1479  </div>
1480  <div class="legend-item status-blue">
1481    <span class="icon-indicator fa fa-wrench"></span>
1482    Maintenance
1483  </div>
1484</div>
1485
1486  </div>
1487
1488    <div id="uptime-tooltip">
1489  <div class="pointer-container">
1490    <div class="pointer-larger"></div>
1491    <div class="pointer-smaller"></div>
1492  </div>
1493  <div class="tooltip-box">
1494    <div class="tooltip-content">
1495      <div class="tooltip-close">
1496        <i class="fa fa-times"></i>
1497      </div>
1498      <div class="date"></div>
1499      <div class="outages">
1500        <div class="outage-field major">
1501          <span class="label">
1502            <i class="component-status page-colors text-color major_outage"></i>
1503            Major outage
1504          </span>
1505          <span class="value-hrs"></span>
1506          <span class="value-mins"></span>
1507        </div>
1508        <div class="outage-field partial">
1509          <span class="label">
1510            <i class="component-status page-colors text-color partial_outage"></i>
1511            Partial outage
1512          </span>
1513          <span class="value-hrs"></span>
1514          <span class="value-mins"></span>
1515        </div>
1516        <div class="no-outages-msg">
1517          No downtime recorded on this day.
1518        </div>
1519        <div class="no-data-msg">
1520          No data exists for this day.
1521        </div>
1522        <div id="major-outage-group-count" class="outage-count">
1523          <i class="component-status page-colors text-color major_outage"></i>
1524          <span class="count"></span>
1525          had a major outage.
1526        </div>
1527        <div id="partial-outage-group-count" class="outage-count">
1528          <i class="component-status page-colors text-color partial_outage"></i>
1529          <span class="count"></span>
1530          had a partial outage.
1531        </div>
1532      </div>
1533      <div class="related-events">
1534        <h3 id="related-event-header">Related</h3>
1535        <ul id="related-events-list"></ul>
1536      </div>
1537      <div class="no-related-msg">
1538        <p>No incidents or maintenance related to this downtime.</p>
1539      </div>
1540    </div>
1541  </div>
1542</div>
1543
1544<script src="https://dka575ofm4ao0.cloudfront.net/assets/vendor/bowser-1643ca34a6d589b2d4d42163a891e4512d5d7657125e09bb5f3d44288114e6bd.js"></script>
vendor: 1 bytes, line 1544
1544
1545<script type="text/javascript">
1546  /**
1547    This file contains the code needed to handle display of the uptime tooltips on status.
1548    Note: because it's in ERB, only ES5 syntax is allowed.
1549  */
1550
1551  window.uptimeData = window.uptimeData || {};
1552  var uptimeData = window.uptimeData;
1553  var timeoutId;
1554  var monthStrings = [
1555    'Jan', 'Feb', 'Mar',
1556    'Apr', 'May', 'Jun',
1557    'Jul', 'Aug', 'Sep',
1558    'Oct', 'Nov', 'Dec'
1559  ];
1560  var EVENT_MAX_LENGTH = 90;
1561
1562  // Detect device (desktop vs. touch device)
1563  function touchDevice() {
1564    var browser = bowser.getParser(window.navigator.userAgent);
1565    // if type is either mobile or tablet, return true
1566    return browser.parse().parsedResult.platform.type !== 'desktop';
1567  }
1568
1569  // Class is in format day-<number>. Convert to just number
1570  function dayNumberFromClass(className) {
1571    return parseInt(className.split('-')[1]);
1572  }
1573
1574  // Class is in format component-<code>. Convert to just code
1575  function componentCodeFromClass(className) {
1576    return className.split('-')[1];
1577  }
1578
1579  // Convert number to string pixel measurement
1580  function intToPixels(number) {
1581    return number.toString() + 'px';
1582  }
1583
1584  function truncate(str) {
1585    return str.substring(0, EVENT_MAX_LENGTH) +
1586      (str.length > EVENT_MAX_LENGTH ? '...' : '');
1587  }
1588
1589  // Tooltip Handling class constructor
1590  function UptimeTooltipHandler(frameWidth) {
1591    this.visible = false;
1592    this.activeDay = {
1593      hovered: false
1594    };
1595    this.tooltip = document.getElementById('uptime-tooltip');
1596    this.frameWidth = frameWidth === undefined ? window.innerWidth : frameWidth;
1597    this.scrolling = false;
1598
1599    window.addEventListener('mousemove', this.tooltipListener.bind(this));
1600    window.addEventListener('orientationchange', this.orientationListener.bind(this));
1601
1602    // on tooltip creation, determine whether to display touch-specific controls
1603    var tooltipCloseButton = document.querySelector('.tooltip-close');
1604
1605    if (touchDevice()) {
1606      var componentsContainer = document.querySelector('.components-container');
1607      componentsContainer.addEventListener('touchstart', this.handleTouch.bind(this));
1608
1609      tooltipCloseButton.addEventListener('touchstart', this.unhoverTooltip.bind(this));
1610    } else {
1611      window.addEventListener('resize', this.resizeListener.bind(this));
1612      // classList not supported by IE < 9
1613      tooltipCloseButton.className += ' hidden';
1614    }
1615
1616    // Handle toggle of group elements
1617    var groupComponents = document.querySelectorAll('[data-js-hook=component-group-opener]');
1618    for (var i = 0; i < groupComponents.length; i++) {
1619      groupComponents[i].addEventListener('click', this.hideTooltip.bind(this));
1620    }
1621
1622    var tooltipBox = document.querySelector('#uptime-tooltip .tooltip-box');
1623    tooltipBox.addEventListener('mouseenter', this.mouseEnteredTooltip.bind(this));
1624    tooltipBox.addEventListener('mouseleave', this.unhoverTooltip.bind(this));
1625  }
1626
1627  // STATUS-801: extracted so the lazy loader (_uptime_showcase_lazy_js) can bind
1628  // focus/blur/keydown handlers on rects that are injected AFTER initial paint.
1629  // Pass a root element to bind only that subtree's rects (avoids re-binding
1630  // existing ones); defaults to the whole document for the inline render path.
1631  function bindUptimeDayRects(root) {
1632    (root || document).querySelectorAll('.uptime-day').forEach(function (rect) {
1633      rect.addEventListener('focus', function (event) {
1634        var tooltipHandler = new UptimeTooltipHandler();
1635        tooltipHandler.updateHoveredDay(event);
1636        tooltipHandler.updateTooltip(event);
1637      });
1638
1639      rect.addEventListener('blur', function () {
1640        var tooltipHandler = new UptimeTooltipHandler();
1641        tooltipHandler.unhoverTooltip();
1642      });
1643
1644      rect.addEventListener('keydown', function (event) {
1645        if (event.key === 'Escape' || event.keyCode === 27) {
1646          var tooltipHandler = new UptimeTooltipHandler();
1647          tooltipHandler.unhoverTooltip();
1648        }
1649      });
1650    });
1651  }
1652  window.bindUptimeDayRects = bindUptimeDayRects;
1653  bindUptimeDayRects(document);
1654
1655  UptimeTooltipHandler.prototype.tooltipListener = function(event) {
1656    if (!this.tooltipHovered) {
1657      this.updateHoveredDay(event);
1658      this.updateTooltip(event);
1659    }
1660  }
1661
1662  // this handler will accommodate for mobile orientation change
1663  UptimeTooltipHandler.prototype.orientationListener = function(event) {
1664    // just close the tooltip
1665    this.unhoverTooltip();
1666  }
1667
1668  UptimeTooltipHandler.prototype.resizeListener = function(event) {
1669    this.frameWidth = window.innerWidth;
1670  }
1671
1672  UptimeTooltipHandler.prototype.handleTouch = function (event) {
1673    if (event.target.classList.contains('uptime-day')) {
1674      event.stopPropagation();
1675      this.bladeTouched(event);
1676    }
1677  }
1678
1679  UptimeTooltipHandler.prototype.mouseEnteredTooltip = function() {
1680    // Necessary to clear the timeout set for closing the tooltip when the mouse
1681    // moves off the blade or timeline, so the tooltip isnt closed on hover
1682    clearTimeout(timeoutId);
1683    // Sets it to null so the timeout can be set later, as clearTimeout only
1684    // cancels the timer, and we need to allow it to be reset in the mouse
1685    // move handler below
1686    timeoutId = null;
1687    this.tooltipHovered = true;
1688  }
1689
1690  UptimeTooltipHandler.prototype.unhoverTooltip = function() {
1691    this.tooltipHovered = false;
1692    this.activeDay.hovered = false;
1693    this.hideTooltip();
1694  }
1695
1696  UptimeTooltipHandler.prototype.bladeTouched = function (event) {
1697    event.preventDefault();
1698    var classes = event.target.getAttribute('class').split(' ');
1699    var componentCode = componentCodeFromClass(classes[1])
1700    var index = dayNumberFromClass(classes[2]);
1701
1702    // If open and tapped on same component and day, close tooltip
1703    if (this.visible && this.activeDay.component === componentCode && this.activeDay.index === index) {
1704      this.hideTooltip();
1705    } else {
1706      this.updateHoveredDay(event);
1707      this.updateTooltip(event);
1708    }
1709  }
1710
1711  UptimeTooltipHandler.prototype.updateHoveredDay = function(event) {
1712    var classes = event.target.getAttribute('class'); // classList doesn't work in IE
1713    var onDay = classes != null && classes.split(' ').indexOf('uptime-day') !== -1;
1714
1715    if (onDay) {
1716      classes = classes.split(' ');
1717
1718      var componentCode = componentCodeFromClass(classes[1]);
1719
1720      this.activeDay = {
1721        index: dayNumberFromClass(classes[2]),
1722        component: componentCode,
1723        bounds: event.target.getBoundingClientRect(),
1724        isGroup: uptimeData[componentCode].component.isGroup,
1725        hovered: true
1726      }
1727    } else {
1728      this.activeDay.hovered = false;
1729    }
1730  }
1731
1732  UptimeTooltipHandler.prototype.updateTooltip = function(event) {
1733    var classes = event.target.getAttribute('class'); // classList doesn't work in IE
1734    var hoveredOnGraphic = classes != null && classes.split(' ').indexOf('availability-time-line-graphic') !== -1;
1735
1736    if (this.activeDay.hovered) {
1737      this.updateTooltipData();
1738      this.positionTooltip();
1739    } else if (this.visible && !this.activeDay.hovered && !hoveredOnGraphic) {
1740      // Important: since this is on mouse move it will be called multiple times
1741      // which will clear timeoutId and reset it to the new value, meaning
1742      // it is a race condition to cancel it
1743      if (!timeoutId) {
1744        var _this = this;
1745        timeoutId = setTimeout(function() {
1746          _this.hideTooltip();
1747          timeoutId = null;
1748        }, 250);
1749      }
1750    }
1751  }
1752
1753  UptimeTooltipHandler.prototype.updateTooltipData = function() {
1754    // Get the data for the day we're hovered on
1755    var day = uptimeData[this.activeDay.component].days[this.activeDay.index];
1756
1757    // Update the date for the tooltip
1758    var date = new Date(day.date);
1759
1760    // Get the component's start date.  Note that it will be undefined here unless it is populated in our database
1761    var startDay = uptimeData[this.activeDay.component].component.startDate;
1762    var startDate = startDay ? new Date(startDay) : null;
1763
1764    // Determine whether current date falls before component's start date.
1765    var beforeStartDate = startDate ? date.getTime() < startDate.getTime() : false;
1766
1767    // UTC necessary since days are passed yyyy-mm-dd, and new Date uses midnight UTC, so local times
1768    // are presented as the day before
1769    var dateString = date.getUTCDate() + " " + monthStrings[date.getUTCMonth()] + " " + date.getUTCFullYear();
1770    document.querySelector('#uptime-tooltip .date').innerHTML = dateString;
1771
1772    // Update the outage fields
1773    if (this.activeDay.isGroup) {
1774      this.updateGroupOutageFields()
1775    } else {
1776      this.updateOutageFields(day.outages.p, day.outages.m, day.related_events, beforeStartDate);
1777    }
1778  }
1779
1780  UptimeTooltipHandler.prototype.hoursFromSeconds = function(s) {
1781    return Math.floor(s / 3600);
1782  }
1783
1784  UptimeTooltipHandler.prototype.minutesFromSeconds = function(s) {
1785    // If less than a minute, round up to 1 minute to show that some outage existed
1786    if (s > 0 && s < 60) {
1787      return 1;
1788    }
1789
1790    // Otherwise use floor
1791    return Math.floor((s % 3600) / 60);
1792  }
1793
1794  UptimeTooltipHandler.prototype.updateGroupOutageFields = function() {
1795    // Hide time info
1796    document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'none';
1797    document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'none';
1798    document.querySelector(".related-events h3").style.display = 'none';
1799    document.querySelector('.no-related-msg').style.display = 'none';
1800
1801    var eventList = document.getElementById("related-events-list")
1802    var cloneList = eventList.cloneNode(false);
1803    eventList.parentNode.replaceChild(cloneList, eventList);
1804
1805    var partialCount = 0;
1806    var majorCount = 0;
1807
1808    /**
1809       We were originally using the operationalCount as part of the no outage copy for group components,
1810       but ultimately decided not to use it. I opted to leave the variable in place in case we ever
1811       decide to use it in the future.
1812     */
1813    var operationalCount = 0;
1814    var noDataCount = 0;
1815    var showcasedComponentsCount = 0;
1816
1817    var components = uptimeData[this.activeDay.component].component.group
1818
1819    for (var i = 0; i < components.length; i++) {
1820      if (!uptimeData[components[i]]) continue;
1821
1822      showcasedComponentsCount++;
1823
1824      var outages = uptimeData[components[i]].days[this.activeDay.index].outages;
1825
1826      var currentDay = uptimeData[components[i]].days[this.activeDay.index];
1827      var currentDate = new Date(currentDay.date);
1828
1829      // Get the component's start date.  Note that it will be undefined here unless it is populated in our database
1830      var startDay = uptimeData[components[i]].component.startDate;
1831      var startDate = startDay ? new Date(startDay) : null;
1832
1833      if (outages.p) {
1834        partialCount += 1;
1835      }
1836
1837      if (outages.m) {
1838        majorCount += 1;
1839      }
1840
1841      // Only increase operational count if component has data for this day
1842      if (!outages.p && !outages.m) {
1843        if (startDate && currentDate.getTime() < startDate.getTime()) {
1844          noDataCount +=1;
1845        }
1846        else {
1847          operationalCount +=1;
1848        }
1849      }
1850    }
1851
1852    document.querySelector('#major-outage-group-count').style.display = majorCount ? 'block' : 'none';
1853    document.querySelector('#partial-outage-group-count').style.display = partialCount ? 'block' : 'none';
1854
1855    document.querySelector('#major-outage-group-count .count').innerText = majorCount + (majorCount === 1 ? " component" : " components");
1856    document.querySelector('#partial-outage-group-count .count').innerText = partialCount + (partialCount === 1 ? " component" : " components ");
1857
1858    // Show no data message only if we do not have data for any showcased components in the group
1859    var showNoDataMessage = noDataCount === showcasedComponentsCount;
1860
1861    // Show no outages message if we have data for the components and no outages in that data
1862    document.querySelector('#uptime-tooltip .no-outages-msg').style.display = (majorCount || partialCount || showNoDataMessage) ? 'none' : 'block';
1863    document.querySelector('#uptime-tooltip .no-data-msg').style.display = showNoDataMessage ? 'block' : 'none';
1864  }
1865
1866  UptimeTooltipHandler.prototype.updateOutageFields = function(partial, major, relatedEvents, beforeStartDate) {
1867    // Hide group info
1868    document.querySelector('#major-outage-group-count').style.display = 'none';
1869    document.querySelector('#partial-outage-group-count').style.display = 'none';
1870
1871    // Show the message that no outage present, if none is present
1872    if (partial || major || beforeStartDate) {
1873      document.querySelector('#uptime-tooltip .no-outages-msg').style.display = 'none';
1874    } else {
1875      document.querySelector('#uptime-tooltip .no-outages-msg').style.display = 'block';
1876    }
1877
1878    if (beforeStartDate) {
1879      document.querySelector('#uptime-tooltip .no-data-msg').style.display = 'block';
1880    }
1881    else {
1882      document.querySelector('#uptime-tooltip .no-data-msg').style.display = 'none';
1883    }
1884
1885    // Update partial outage field if an outage exists, otherwise hide it
1886    if (partial) {
1887      var hrs = this.hoursFromSeconds(partial);
1888      var mins = this.minutesFromSeconds(partial);
1889      document.querySelector('#uptime-tooltip .outage-field.partial .value-hrs').innerHTML = hrs.toString() + ' hrs';
1890      document.querySelector('#uptime-tooltip .outage-field.partial .value-mins').innerHTML = mins.toString() + ' mins';
1891      document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'flex';
1892    } else {
1893       document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'none';
1894    }
1895
1896    // Update major outage field if an outage exists, otherwise hide it
1897    if (major) {
1898      var hrs = this.hoursFromSeconds(major);
1899      var mins = this.minutesFromSeconds(major);
1900      document.querySelector('#uptime-tooltip .outage-field.major .value-hrs').innerHTML = hrs.toString() + ' hrs';
1901      document.querySelector('#uptime-tooltip .outage-field.major .value-mins').innerHTML = mins.toString() + ' mins';
1902      document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'flex';
1903    } else {
1904      document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'none';
1905    }
1906
1907    var eventList = document.getElementById("related-events-list")
1908    var cloneList = eventList.cloneNode(false);
1909    document.querySelector(".related-events h3").style.display = (relatedEvents.length ? 'block' : 'none');
1910
1911    for (var i = 0; i < relatedEvents.length; i++) {
1912      var listItem = document.createElement("li");
1913      listItem.className = "related-event";
1914      var anchor = document.createElement("a");
1915      anchor.className = "related-event-link";
1916      anchor.target = "_blank";
1917      anchor.href = window.Routes.incident_path(relatedEvents[i].code);
1918
1919
1920      var text = document.createTextNode(truncate(relatedEvents[i].name));
1921      anchor.appendChild(text);
1922      listItem.appendChild(anchor);
1923      cloneList.appendChild(listItem);
1924    }
1925
1926    const displayNoRelatedMsg = ((major || partial) && !relatedEvents.length);
1927    document.querySelector('.no-related-msg').style.display = (displayNoRelatedMsg ? 'block' : 'none');
1928
1929    eventList.parentNode.replaceChild(cloneList, eventList);
1930  }
1931
1932  UptimeTooltipHandler.prototype.positionTooltip = function() {
1933    this.calculatePointerCenter();
1934    this.calculateBoxPosition();
1935
1936    // show tooltip
1937    this.tooltip.style.display = 'block';
1938
1939    // position pointer
1940    var pointer = this.tooltip.getElementsByClassName('pointer-container')[0];
1941    pointer.style.left = intToPixels(this.pointerCenter.x - 8);
1942    pointer.style.top = intToPixels(this.pointerCenter.y - 5);
1943
1944    // position display box
1945    var box = this.tooltip.getElementsByClassName('tooltip-box')[0];
1946    box.style.left = intToPixels(this.boxLeft);
1947    box.style.top = intToPixels(this.pointerCenter.y + 5);
1948
1949    this.visible = true;
1950  }
1951
1952  UptimeTooltipHandler.prototype.calculatePointerCenter = function() {
1953    var bounds = this.activeDay.bounds;
1954    var rectLeft = bounds.left + window.pageXOffset;
1955    var rectBottom = bounds.bottom + window.pageYOffset;
1956    var rectWidth = bounds.right - bounds.left;
1957
1958    this.pointerCenter = {
1959      x: rectLeft + Math.floor(rectWidth / 2),
1960      y: rectBottom + 5
1961    }
1962  }
1963
1964  UptimeTooltipHandler.prototype.calculateBoxPosition = function() {
1965    var sideWidth = 162.5;
1966    if (this.pointerCenter.x - sideWidth < 0) {
1967      this.boxLeft = 0;
1968    } else if (this.pointerCenter.x + sideWidth > this.frameWidth) {
1969      this.boxLeft = this.frameWidth - sideWidth * 2;
1970    } else {
1971      this.boxLeft = this.pointerCenter.x - sideWidth;
1972    }
1973  }
1974
1975  UptimeTooltipHandler.prototype.hideTooltip = function() {
1976    this.tooltip.style.display = 'none';
1977    this.visible = false;
1978  }
1979
1980  new UptimeTooltipHandler();
1981
1982</script>
1982
1983
1984
1985    
1985<script type="text/javascript">
1986  /**
1987   * STATUS-801: viewport-triggered loader for the 90-day uptime showcase.
1988   *
1989   * When LAZY_UPTIME_SHOWCASE is enabled the status document ships WITHOUT the
1990   * per-component SVG bars and the multi-MB inline `uptimeData` blob (that inline
1991   * payload is what caused `200 OK` + `ERR_HTTP2_PROTOCOL_ERROR` truncation on
1992   * large pages). Each showcase-eligible component instead renders a small
1993   * placeholder (`[data-uptime-lazy="<code>"]`). This script watches those
1994   * placeholders and, as they scroll into view, fetches their bars in small
1995   * batches from `status#uptime_showcase`, replaces the placeholder with the
1996   * returned markup, merges the tooltip data into `window.uptimeData`, and wires
1997   * up hover/keyboard tooltips + responsive (30/60/90-day) resizing.
1998   *
1999   * ES5 only (matches the rest of the status inline scripts). No hard dependency
2000   * on fetch/IntersectionObserver: falls back gracefully when unavailable.
2001   */
2002  (function () {
2003    var ENDPOINT = "/uptime_showcase";
2004    var BATCH_LIMIT = 60;              // must stay <= SHOWCASE_BATCH_LIMIT server-side
2005    var FLUSH_DELAY_MS = 60;           // coalesce rapidly-observed placeholders
2006    var MAX_WIDTH_30_DAYS = 600;
2007    var MAX_WIDTH_60_DAYS = 1024;
2008    var PRELOAD_MARGIN = '250px 0px';  // start fetching just before they scroll in
2009
2010    // code -> {ninety, sixty, thirty} for responsive legend updates.
2011    var uptimeValues = {};
2012    // code -> true while queued/in-flight, to avoid duplicate requests.
2013    var inFlight = {};
2014    var queue = [];
2015    var flushTimer = null;
2016    var observer = null;
2017
2018    function init() {
2019      var placeholders = document.querySelectorAll('[data-uptime-lazy]');
2020      if (!placeholders.length) return;
2021
2022      window.uptimeData = window.uptimeData || {};
2023
2024      if ('IntersectionObserver' in window) {
2025        observer = new IntersectionObserver(onIntersect, { rootMargin: PRELOAD_MARGIN });
2026        for (var i = 0; i < placeholders.length; i++) {
2027          observer.observe(placeholders[i]);
2028        }
2029      } else {
2030        // Older browsers: no lazy behaviour, just load everything in batches.
2031        for (var j = 0; j < placeholders.length; j++) {
2032          enqueue(placeholders[j].getAttribute('data-uptime-lazy'));
2033        }
2034      }
2035
2036      var resizeTimer;
2037      window.addEventListener('resize', function () {
2038        clearTimeout(resizeTimer);
2039        resizeTimer = setTimeout(resizeSvgViewBoxes, 150);
2040      });
2041    }
2042
2043    function onIntersect(entries) {
2044      for (var i = 0; i < entries.length; i++) {
2045        if (entries[i].isIntersecting) {
2046          enqueue(entries[i].target.getAttribute('data-uptime-lazy'));
2047        }
2048      }
2049    }
2050
2051    function enqueue(code) {
2052      if (!code || inFlight[code]) return;
2053      inFlight[code] = true;
2054      queue.push(code);
2055      if (!flushTimer) flushTimer = setTimeout(flush, FLUSH_DELAY_MS);
2056    }
2057
2058    function flush() {
2059      flushTimer = null;
2060      if (!queue.length) return;
2061      var batch = queue.splice(0, BATCH_LIMIT);
2062      fetchBatch(batch);
2063      if (queue.length && !flushTimer) flushTimer = setTimeout(flush, FLUSH_DELAY_MS);
2064    }
2065
2066    function fetchBatch(codes) {
2067      var xhr = new XMLHttpRequest();
2068      xhr.open('GET', ENDPOINT + '?components=' + encodeURIComponent(codes.join(',')), true);
2069      xhr.setRequestHeader('Accept', 'application/json');
2070      xhr.onreadystatechange = function () {
2071        if (xhr.readyState !== 4) return;
2072        if (xhr.status >= 200 && xhr.status < 300) {
2073          var data;
2074          try { data = JSON.parse(xhr.responseText); }
2075          catch (e) { release(codes); return; }
2076          applyBatch(data, codes);
2077        } else {
2078          // Transient failure: allow these codes to be retried if re-observed.
2079          release(codes);
2080        }
2081      };
2082      xhr.send();
2083    }
2084
2085    // Free codes so a future intersection can retry them (e.g. after a 5xx).
2086    function release(codes) {
2087      for (var i = 0; i < codes.length; i++) inFlight[codes[i]] = false;
2088    }
2089
2090    function applyBatch(data, codes) {
2091      var timelines = data.timelines || {};
2092      for (var key in timelines) {
2093        if (timelines.hasOwnProperty(key)) window.uptimeData[key] = timelines[key];
2094      }
2095
2096      var values = data.values || [];
2097      for (var v = 0; v < values.length; v++) {
2098        uptimeValues[values[v].component] = values[v];
2099      }
2100
2101      var components = data.components || {};
2102      for (var c = 0; c < codes.length; c++) {
2103        var code = codes[c];
2104        var placeholder = document.querySelector('[data-uptime-lazy="' + code + '"]');
2105        if (!placeholder) continue;
2106        if (observer) observer.unobserve(placeholder);
2107
2108        var html = components[code];
2109        if (!html) {
2110          // Server returned no markup for this code (not actually showcased):
2111          // drop the placeholder and stop retrying.
2112          if (placeholder.parentNode) placeholder.parentNode.removeChild(placeholder);
2113          continue;
2114        }
2115
2116        // Replace the neutral placeholder with the fetched `.uptime-90-days-wrapper`
2117        // so the resulting DOM matches the inline (non-lazy) render exactly.
2118        var holder = document.createElement('div');
2119        holder.innerHTML = html;
2120        var node = holder.firstElementChild;
2121        if (node && placeholder.parentNode) {
2122          placeholder.parentNode.replaceChild(node, placeholder);
2123          if (window.bindUptimeDayRects) window.bindUptimeDayRects(node);
2124        }
2125      }
2126
2127      resizeSvgViewBoxes();
2128    }
2129
2130    /* ----- responsive resize (adapted from components_js) ----------------- */
2131
2132    function calculateViewbox(dayCount, rectWidth, rectPadding) {
2133      var viewBox = [];
2134      if (dayCount === 90) {
2135        viewBox.push(0);
2136      } else {
2137        var offset = 90 - dayCount;
2138        viewBox.push((offset * rectWidth) + (rectPadding * offset));
2139      }
2140      viewBox.push(0);
2141      viewBox.push((rectWidth * dayCount) + (rectPadding * (dayCount - 1)));
2142      viewBox.push(34);
2143      return viewBox.join(' ');
2144    }
2145
2146    function getKeyAndCount(width) {
2147      if (width <= MAX_WIDTH_30_DAYS) return { dayCount: 30, uptimeKey: 'thirty' };
2148      if (width <= MAX_WIDTH_60_DAYS) return { dayCount: 60, uptimeKey: 'sixty' };
2149      return { dayCount: 90, uptimeKey: 'ninety' };
2150    }
2151
2152    function setUptimeValue(values, uptimeKey) {
2153      var current = document.querySelector('.legend-item-' + values.component);
2154      if (!current) return;
2155      var clone = current.cloneNode(false);
2156      var uptimeSpan = document.createElement('span');
2157      uptimeSpan.id = 'uptime-percent-' + values.component;
2158      uptimeSpan.innerText = values[uptimeKey];
2159      clone.appendChild(uptimeSpan);
2160      clone.appendChild(document.createTextNode(' % uptime'));
2161      current.parentNode.replaceChild(clone, current);
2162    }
2163
2164    function setDayCount(el, dayCount) {
2165      var clone = el.cloneNode(false);
2166      var dateSpan = document.createElement('span');
2167      dateSpan.className = 'availability-time-line-legend-day-count';
2168      dateSpan.innerText = dayCount;
2169      clone.appendChild(dateSpan);
2170      clone.appendChild(document.createTextNode(' days ago'));
2171      el.parentNode.replaceChild(clone, el);
2172    }
2173
2174    function resizeSvgViewBoxes() {
2175      var svgs = document.getElementsByClassName('availability-time-line-graphic');
2176      if (!svgs.length) return;
2177
2178      var rects = svgs[0].getElementsByTagName('rect');
2179      if (rects.length < 2) return;
2180
2181      var rectWidth = parseInt(rects[0].getAttribute('width'));
2182      var rectPadding = parseInt(rects[1].getAttribute('x')) - parseInt(rects[0].getAttribute('x')) - rectWidth;
2183      var info = getKeyAndCount(window.innerWidth);
2184      var newViewbox = calculateViewbox(info.dayCount, rectWidth, rectPadding);
2185
2186      for (var i = 0; i < svgs.length; i++) {
2187        if (svgs[i].getAttribute('viewBox') !== newViewbox) {
2188          svgs[i].setAttribute('viewBox', newViewbox);
2189        }
2190      }
2191
2192      var dayCountElements = document.querySelectorAll('.legend-item-date-range:first-of-type');
2193      for (var d = 0; d < dayCountElements.length; d++) {
2194        setDayCount(dayCountElements[d], info.dayCount);
2195      }
2196
2197      for (var code in uptimeValues) {
2198        if (uptimeValues.hasOwnProperty(code)) setUptimeValue(uptimeValues[code], info.uptimeKey);
2199      }
2200
2201      var uptimeLinkVar = document.querySelector('.components-uptime-link > var');
2202      if (uptimeLinkVar) uptimeLinkVar.innerHTML = info.dayCount;
2203    }
2204
2205    if (document.readyState === 'loading') {
2206      document.addEventListener('DOMContentLoaded', init);
2207    } else {
2208      init();
2209    }
2210  })();
2211</script>
2211
2212
2213
2214
2215
2216        <div class="custom-metrics-container" id="custom-metrics-container">
2217          <div class="timeframes-container">
2218            <a class="font-largest no-link" id="system-metrics" href="#system-metrics">System Metrics</a>
2219            <a href="#" class="timeframe color-secondary font-regular border-color" data-js-hook="data-time-period-toggle" data-time-period="month">Month</a>
2220            <a href="#" class="timeframe color-secondary font-regular border-color" data-js-hook="data-time-period-toggle" data-time-period="week"><span class="translation_missing" title="translation missing: en.week">Week</span></a>
2221            <a href="#" class="timeframe active color-secondary font-regular border-color" data-js-hook="data-time-period-toggle" data-time-period="day">Day</a>
2222          </div>
2223          <div class="metrics-container">
2224              <div class="metric border-color">
2225                <div class="metric-meta font-large">
2226                  <div class="metric-name color-primary">
2227                    Active Linux Builds for Open Source projects
2228                                      </div>
2229
2230                    <div data-js-hook="metrics-display-current-f9xnl1j783xl" class="metric-average color-secondary"><span class="translation_missing" title="translation missing: en.fetching">Fetching</span></div>
2231                </div>
2232                   <div class="metrics-display-graph">
2233                    <div class="graph-container" id="metrics-display-graph-container-f9xnl1j783xl" data-js-hook= "metrics-display-graph-container-f9xnl1j783xl"></div>
2234                  </div>
2235              </div>
2236              <div class="metric border-color">
2237                <div class="metric-meta font-large">
2238                  <div class="metric-name color-primary">
2239                    Backlog Linux Builds for Open Source projects
2240                                      </div>
2241
2242                    <div data-js-hook="metrics-display-current-td6nbzppbz2j" class="metric-average color-secondary"><span class="translation_missing" title="translation missing: en.fetching">Fetching</span></div>
2243                </div>
2244                   <div class="metrics-display-graph">
2245                    <div class="graph-container" id="metrics-display-graph-container-td6nbzppbz2j" data-js-hook= "metrics-display-graph-container-td6nbzppbz2j"></div>
2246                  </div>
2247              </div>
2248          </div>
2249        </div>
2250
2251
2252      <div class="incidents-list format-expanded">
2253        <h2 class="font-largest no-link" id="past-incidents">Past Incidents</h2>
2254          
2255  <div class="status-day font-regular no-incidents">
2256    <h3 class="date border-color font-large">Oct <var data-var="date"> 2</var>, <var data-var="year">2026</var></h3>
2257        <p class="color-secondary">No incidents reported today.</p>
2258  </div>
2259
2260          
2261  <div class="status-day font-regular no-incidents">
2262    <h3 class="date border-color font-large">Oct <var data-var="date"> 1</var>, <var data-var="year">2026</var></h3>
2263        <p class="color-secondary">No incidents reported.</p>
2264  </div>
2265
2266          
2267  <div class="status-day font-regular no-incidents">
2268    <h3 class="date border-color font-large">Sep <var data-var="date">30</var>, <var data-var="year">2026</var></h3>
2269        <p class="color-secondary">No incidents reported.</p>
2270  </div>
2271
2272          
2273  <div class="status-day font-regular no-incidents">
2274    <h3 class="date border-color font-large">Sep <var data-var="date">29</var>, <var data-var="year">2026</var></h3>
2275        <p class="color-secondary">No incidents reported.</p>
2276  </div>
2277
2278          
2279  <div class="status-day font-regular no-incidents">
2280    <h3 class="date border-color font-large">Sep <var data-var="date">28</var>, <var data-var="year">2026</var></h3>
2281        <p class="color-secondary">No incidents reported.</p>
2282  </div>
2283
2284          
2285  <div class="status-day font-regular no-incidents">
2286    <h3 class="date border-color font-large">Sep <var data-var="date">27</var>, <var data-var="year">2026</var></h3>
2287        <p class="color-secondary">No incidents reported.</p>
2288  </div>
2289
2290          
2291  <div class="status-day font-regular no-incidents">
2292    <h3 class="date border-color font-large">Sep <var data-var="date">26</var>, <var data-var="year">2026</var></h3>
2293        <p class="color-secondary">No incidents reported.</p>
2294  </div>
2295
2296          
2297  <div class="status-day font-regular no-incidents">
2298    <h3 class="date border-color font-large">Sep <var data-var="date">25</var>, <var data-var="year">2026</var></h3>
2299        <p class="color-secondary">No incidents reported.</p>
2300  </div>
2301
2302          
2303  <div class="status-day font-regular no-incidents">
2304    <h3 class="date border-color font-large">Sep <var data-var="date">24</var>, <var data-var="year">2026</var></h3>
2305        <p class="color-secondary">No incidents reported.</p>
2306  </div>
2307
2308          
2309  <div class="status-day font-regular no-incidents">
2310    <h3 class="date border-color font-large">Sep <var data-var="date">23</var>, <var data-var="year">2026</var></h3>
2311        <p class="color-secondary">No incidents reported.</p>
2312  </div>
2313
2314          
2315  <div class="status-day font-regular no-incidents">
2316    <h3 class="date border-color font-large">Sep <var data-var="date">22</var>, <var data-var="year">2026</var></h3>
2317        <p class="color-secondary">No incidents reported.</p>
2318  </div>
2319
2320          
2321  <div class="status-day font-regular no-incidents">
2322    <h3 class="date border-color font-large">Sep <var data-var="date">21</var>, <var data-var="year">2026</var></h3>
2323        <p class="color-secondary">No incidents reported.</p>
2324  </div>
2325
2326          
2327  <div class="status-day font-regular no-incidents">
2328    <h3 class="date border-color font-large">Sep <var data-var="date">20</var>, <var data-var="year">2026</var></h3>
2329        <p class="color-secondary">No incidents reported.</p>
2330  </div>
2331
2332          
2333  <div class="status-day font-regular no-incidents">
2334    <h3 class="date border-color font-large">Sep <var data-var="date">19</var>, <var data-var="year">2026</var></h3>
2335        <p class="color-secondary">No incidents reported.</p>
2336  </div>
2337
2338          
2339  <div class="status-day font-regular no-incidents">
2340    <h3 class="date border-color font-large">Sep <var data-var="date">18</var>, <var data-var="year">2026</var></h3>
2341        <p class="color-secondary">No incidents reported.</p>
2342  </div>
2343
2344      </div>
2345
2346
2347      <div class="page-footer border-color font-small">
2348          <a href="/history" class="history-footer-link"><span style="font-family:arial" aria-hidden="true">&larr;</span> Incident History</a>
2349
2350        <span class="color-secondary powered-by"><a class="color-secondary" target="_blank" rel="noopener noreferrer nofollow" href="https://www.atlassian.com/software/statuspage?utm_campaign=www.traviscistatus.com&amp;utm_content=SP-notifications&amp;utm_medium=powered-by&amp;utm_source=inapp">Powered by Atlassian Statuspage</a></span>
2351      </div>
2352    </div>
2353
2354    
2355
2356  </div>
2357
2358
2359
2360  <!-- custom metrics stuff -->
2361  
2362
2363
2364
2365
2366    
2366<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_manifest-b790849ccb41192b3f7d9c14d5a4a6d5142add81fc8522649ca5c82f6a1fbb0e.js"></script>
2366
2367    <div id="cpt-notification-container" role="status" aria-live="polite" aria-atomic="true"></div>
2368    
2369
2370
2371
2372
2373    <!-- all of the content_for stuff -->
2374      
2374<script src="https://dka575ofm4ao0.cloudfront.net/assets/register_subscription_form-589b657fec607087fc5c740c568270907310bc4f6aaa20256e70f01b103025ca.js"></script>
2374
2375
2376  
2376<script type="text/javascript">
2377      $(function() {
2378          SP.currentPage.registerSubscriptionForm('email');
2379
2380
2381          SP.currentPage.registerSubscriptionForm('webhook');
2382
2383      });
2384
2385
2386
2387
2388
2389  </script>
2389
2390  
2390<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_common-a7b1e9f22a2c94a83d347ec517cabf21494ca11867ebf891f46f89c9b4101811.js"></script>
2390
2391    
2391<script>
2392      SP.pollForChanges('/api/v2/status.json');
2393    </script>
2393
2394
2395  
2395<script>
2396    $(function() {
2397      $('.tool').tooltipster({
2398        animationDuration: 100,
2399        contentAsHTML: true,
2400        delay: 100,
2401        theme: 'tooltipster-borderless',
2402        functionInit: function (instance, helper) {
2403          var $origin = $(helper.origin),
2404              dataOptions = $origin.attr('data-tooltip-config');
2405          if (dataOptions){
2406            dataOptions = JSON.parse(dataOptions);
2407            $.each(dataOptions, function(name, option){
2408                instance.option(name, option);
2409            });
2410          }
2411        }
2412      });
2413      // clicks on first tab in subscribe popout since we won't know which is first
2414      // upon construction in the ruby code
2415      $('.updates-dropdown-nav > a').eq(0).click();
2416
2417      // twitter follow button needs some margin
2418      $('.twitter-follow-button').css('margin-right', '6px');
2419    });
2420
2421    $(function() {
2422      // open/close component groups
2423      HRB.utils.djshook('component-group-opener').on('click', function() {
2424        var groupParentIndicator = $(this).find('.group-parent-indicator');
2425        groupParentIndicator.toggleClass('fa-plus-square-o').toggleClass('fa-minus-square-o').end().parent().toggleClass('open');
2426        toggleGroup(groupParentIndicator)
2427      });
2428    });
2429
2430    $(function() {
2431      HRB.utils.djshook('component-group-opener').on('keydown', function(event) {
2432        if (event.key !== "Enter" && event.key !== " ") {
2433          return;
2434        }
2435        event.preventDefault()
2436        var groupParentIndicator = $(this).find('.group-parent-indicator');
2437        groupParentIndicator.toggleClass('fa-plus-square-o').toggleClass('fa-minus-square-o').end().parent().toggleClass('open');
2438        toggleGroup(groupParentIndicator)
2439      });
2440    });
2441
2442    function toggleGroup(groupParentIndicator) {
2443      var isOpen = groupParentIndicator.attr('aria-expanded')
2444      if (isOpen == 'false') {
2445          groupParentIndicator.attr('aria-expanded', 'true');
2446        } else {
2447          groupParentIndicator.attr('aria-expanded', 'false');
2448        }
2449    }
2450
2451    $(function() {
2452      $(document).on('ajax:complete', '.modal.in', function(e) {
2453        // Close the active modal.
2454        $('.modal.in').modal('hide');
2455      });
2456    });
2457
2458  </script>
2458
2459  
2459<script src="https://dka575ofm4ao0.cloudfront.net/assets/vendor/highstock.min-a7181c8f093438143dae37524f8463a97e2503789bc322732d3141f2c00c1c1a.js"></script>
2459
2460
2461  
2461<script>
2462    //<![CDATA[
2463    String.prototype.commafy = function () {
2464      return this.replace(/(^|[^\w.])(\d{4,})/g, function($0, $1, $2) {
2465        return $1 + $2.replace(/\d(?=(?:\d\d\d)+(?!\d))/g, "$&,");
2466      });
2467    }
2468
2469    Number.prototype.commafy = function () {
2470      return String(this).commafy();
2471    }
2472
2473    $(function() {
2474      SP.currentPage.numberToDecimalPlaces = function(num, dec) {
2475        if (dec == 0) {
2476          return Math.round(num).commafy();
2477        }
2478
2479        newnum = num.toFixed(dec)
2480        var finalValue;
2481
2482        // this gets rid of the 100.000% thing
2483        if (num == parseInt(newnum))
2484          finalValue = Math.round(num);
2485        else
2486          finalValue = newnum;
2487
2488        return finalValue.commafy();
2489      }
2490
2491      SP.currentPage.getDataForTimePeriod = function(period) {
2492          $.ajax({
2493            type: "GET",
2494            // this line must be end up with "//status.*" type of URLs (no protocol, just leading slashes). customers use SSL through us or by offloading with
2495            // cloudflare or something like it and the request.protocol the server sees is different than what the browser sees
2496            url: "//www.traviscistatus.com/metrics-display/f9xnl1j783xl/_.json".replace('_', period)
2497          }).done(function(metricsDisplay, textStatus, xhr) {
2498            var summary = metricsDisplay.summary
2499              , $metricSummaryLabel = HRB.utils.djshook('metrics-display-current-f9xnl1j783xl')
2500              , $graphContainer = HRB.utils.djshook('metrics-display-graph-container-f9xnl1j783xl');
2501            var errorMsg = null;
2502
2503            if(summary === "unavailable") {
2504              errorMsg = 'We\'re having issues retrieving data for <strong>Active Linux Builds for Open Source projects</strong>.</div>';
2505            } else if(summary) {
2506              // we need to do a basic check to make sure we have any data at all
2507              var hasDataRollupsAvailable = false;
2508              for(var h = 0; h < metricsDisplay.metrics.length; h++) {
2509                if(metricsDisplay.metrics[h].data.length > 0) {
2510                  hasDataRollupsAvailable = true;
2511                  break;
2512                }
2513              }
2514              if(!hasDataRollupsAvailable) {
2515                errorMsg = "Oops! No data has been indexed for <strong>Active Linux Builds for Open Source projects</strong> for this time period yet.";
2516              }
2517            } else {
2518              errorMsg = "Failed to load. <strong>Active Linux Builds for Open Source projects</strong>";
2519            }
2520
2521            if(errorMsg !== null) {
2522              $metricSummaryLabel.text("--"); // display -- instead of number
2523              $graphContainer.html('<div class="small"  style="text-align:center;">' + errorMsg + '</div>'); // removed .parent().find('.metric-meta').remove() so name still shows
2524              $graphContainer.removeAttr("style");
2525              return;
2526            }
2527
2528            $graphContainer.show();
2529            $graphContainer.attr("style", "height: 120px"); // set style after error message removed it
2530            // proceed since we have data
2531            $metricSummaryLabel.text(SP.currentPage.numberToDecimalPlaces(summary['mean'], 0 ) + ' jobs');
2532
2533            var metricDataPoints = {}
2534              , intervalMsec = metricsDisplay.period.interval * 1000;
2535
2536            var startingBucketMsec = parseInt((new Date()).getTime() / intervalMsec) * intervalMsec;
2537
2538            for(var h = 0; h < metricsDisplay.metrics.length; h++) {
2539              metricDataPoints[metricsDisplay.metrics[h].metric.id] = []
2540              var data = metricsDisplay.metrics[h].data
2541                , currentBucketMsec = startingBucketMsec;
2542
2543              for(var i = metricsDisplay.period.count; i > 0; i--) {
2544                // loop over the data and pull out the data point with the following characteristics
2545                //  -> closest to currentBucketMsec
2546                //  -> without being greater than currentMsecBucket
2547                //  -> without being more than 1 intervalMsec bucket away
2548                var valueToUse = null;
2549                for(var j = data.length - 1; j >= 0; j--) {
2550                  var currentTimestampMsec = data[j].timestamp * 1000;
2551                  if(currentTimestampMsec <= currentBucketMsec && currentTimestampMsec > (currentBucketMsec - intervalMsec)) {
2552                    valueToUse = data[j].value;
2553                    // console.log("Using ts:" + currentTimestampMsec + " with value:" + valueToUse + " for bucket:" + currentBucketMsec);
2554                    break;
2555                  }
2556                }
2557
2558                // local time
2559                var offset = -1 * (new Date()).getTimezoneOffset() * 60 * 1000;
2560
2561                metricDataPoints[metricsDisplay.metrics[h].metric.id].push([currentBucketMsec + offset, valueToUse])
2562                  currentBucketMsec -= intervalMsec;
2563              }
2564
2565              metricDataPoints[metricsDisplay.metrics[h].metric.id].reverse();
2566            }
2567                  // set Global options
2568      Highcharts.setOptions({
2569        lang: {
2570          thousandsSep: ','
2571        }
2572      });
2573
2574      $('#metrics-display-graph-container-f9xnl1j783xl').highcharts('StockChart', {
2575        plotOptions : {
2576          series : {
2577            animation : false,
2578            color : '#0068FF',
2579            connectNulls: false
2580          },
2581        },
2582
2583        chart : {
2584          backgroundColor: '#fff'
2585        },
2586
2587        title : {
2588          text: '',
2589          style: {
2590                display: 'none',
2591             }
2592        },
2593
2594        credits : {
2595          enabled : false
2596        },
2597
2598        exporting : {
2599          enabled : false
2600        },
2601
2602        rangeSelector : {
2603          enabled : false
2604        },
2605
2606        scrollbar : {
2607          enabled : false
2608        },
2609
2610        navigator : {
2611          enabled : false
2612        },
2613
2614        xAxis: {
2615          gridLineColor : 'rgba(204,225,255,.8)',
2616          labels: {
2617            style : {
2618              color: '#8794A0'
2619            }
2620          },
2621          lineColor: '#CCE1FF',
2622        },
2623
2624        yAxis: {
2625          gridLineColor : 'rgba(204,225,255,.5)',
2626          labels: {
2627            align: 'left',
2628            x: 5,
2629            y: 3,
2630            style : {
2631              color: '#8794A0'
2632            },
2633            enabled : true
2634          },
2635          showLastLabel: true,
2636                           tickPixelInterval: 40,
2637
2638        },
2639
2640        series : [
2641              {
2642      name : 'Active Linux Builds for Open Source projects',
2643      data : metricDataPoints['8r2tgpgjfcmf'],
2644      tooltip: {
2645        valueSuffix: ' jobs'
2646      },
2647      enableMouseTracking : ($(window).outerWidth() > 480) && true
2648    }
2649
2650        ],
2651
2652        tooltip: {
2653          borderWidth: 0,
2654          enabled: ($(window).outerWidth() > 480) && true,
2655          headerFormat: "<span style='font-size: 10px'>{point.key}  </span>",
2656          hideDelay: 300,
2657          pointFormat: "<span style='color:{point.color}'>●</span>  <b>{point.y}</b><br/>",
2658          positioner: function() { return {x: 0, y: 0 }; },
2659          shadow: false,
2660          shape: "square",
2661          split: false
2662        }
2663      });
2664
2665          });
2666          $.ajax({
2667            type: "GET",
2668            // this line must be end up with "//status.*" type of URLs (no protocol, just leading slashes). customers use SSL through us or by offloading with
2669            // cloudflare or something like it and the request.protocol the server sees is different than what the browser sees
2670            url: "//www.traviscistatus.com/metrics-display/td6nbzppbz2
2670j/_.json".replace('_', period)
2671          }).done(function(metricsDisplay, textStatus, xhr) {
2672            var summary = metricsDisplay.summary
2673              , $metricSummaryLabel = HRB.utils.djshook('metrics-display-current-td6nbzppbz2j')
2674              , $graphContainer = HRB.utils.djshook('metrics-display-graph-container-td6nbzppbz2j');
2675            var errorMsg = null;
2676
2677            if(summary === "unavailable") {
2678              errorMsg = 'We\'re having issues retrieving data for <strong>Backlog Linux Builds for Open Source projects</strong>.</div>';
2679            } else if(summary) {
2680              // we need to do a basic check to make sure we have any data at all
2681              var hasDataRollupsAvailable = false;
2682              for(var h = 0; h < metricsDisplay.metrics.length; h++) {
2683                if(metricsDisplay.metrics[h].data.length > 0) {
2684                  hasDataRollupsAvailable = true;
2685                  break;
2686                }
2687              }
2688              if(!hasDataRollupsAvailable) {
2689                errorMsg = "Oops! No data has been indexed for <strong>Backlog Linux Builds for Open Source projects</strong> for this time period yet.";
2690              }
2691            } else {
2692              errorMsg = "Failed to load. <strong>Backlog Linux Builds for Open Source projects</strong>";
2693            }
2694
2695            if(errorMsg !== null) {
2696              $metricSummaryLabel.text("--"); // display -- instead of number
2697              $graphContainer.html('<div class="small"  style="text-align:center;">' + errorMsg + '</div>'); // removed .parent().find('.metric-meta').remove() so name still shows
2698              $graphContainer.removeAttr("style");
2699              return;
2700            }
2701
2702            $graphContainer.show();
2703            $graphContainer.attr("style", "height: 120px"); // set style after error message removed it
2704            // proceed since we have data
2705            $metricSummaryLabel.text(SP.currentPage.numberToDecimalPlaces(summary['mean'], 0 ) + ' jobs');
2706
2707            var metricDataPoints = {}
2708              , intervalMsec = metricsDisplay.period.interval * 1000;
2709
2710            var startingBucketMsec = parseInt((new Date()).getTime() / intervalMsec) * intervalMsec;
2711
2712            for(var h = 0; h < metricsDisplay.metrics.length; h++) {
2713              metricDataPoints[metricsDisplay.metrics[h].metric.id] = []
2714              var data = metricsDisplay.metrics[h].data
2715                , currentBucketMsec = startingBucketMsec;
2716
2717              for(var i = metricsDisplay.period.count; i > 0; i--) {
2718                // loop over the data and pull out the data point with the following characteristics
2719                //  -> closest to currentBucketMsec
2720                //  -> without being greater than currentMsecBucket
2721                //  -> without being more than 1 intervalMsec bucket away
2722                var valueToUse = null;
2723                for(var j = data.length - 1; j >= 0; j--) {
2724                  var currentTimestampMsec = data[j].timestamp * 1000;
2725                  if(currentTimestampMsec <= currentBucketMsec && currentTimestampMsec > (currentBucketMsec - intervalMsec)) {
2726                    valueToUse = data[j].value;
2727                    // console.log("Using ts:" + currentTimestampMsec + " with value:" + valueToUse + " for bucket:" + currentBucketMsec);
2728                    break;
2729                  }
2730                }
2731
2732                // local time
2733                var offset = -1 * (new Date()).getTimezoneOffset() * 60 * 1000;
2734
2735                metricDataPoints[metricsDisplay.metrics[h].metric.id].push([currentBucketMsec + offset, valueToUse])
2736                  currentBucketMsec -= intervalMsec;
2737              }
2738
2739              metricDataPoints[metricsDisplay.metrics[h].metric.id].reverse();
2740            }
2741                  // set Global options
2742      Highcharts.setOptions({
2743        lang: {
2744          thousandsSep: ','
2745        }
2746      });
2747
2748      $('#metrics-display-graph-container-td6nbzppbz2j').highcharts('StockChart', {
2749        plotOptions : {
2750          series : {
2751            animation : false,
2752            color : '#0068FF',
2753            connectNulls: false
2754          },
2755        },
2756
2757        chart : {
2758          backgroundColor: '#fff'
2759        },
2760
2761        title : {
2762          text: '',
2763          style: {
2764                display: 'none',
2765             }
2766        },
2767
2768        credits : {
2769          enabled : false
2770        },
2771
2772        exporting : {
2773          enabled : false
2774        },
2775
2776        rangeSelector : {
2777          enabled : false
2778        },
2779
2780        scrollbar : {
2781          enabled : false
2782        },
2783
2784        navigator : {
2785          enabled : false
2786        },
2787
2788        xAxis: {
2789          gridLineColor : 'rgba(204,225,255,.8)',
2790          labels: {
2791            style : {
2792              color: '#8794A0'
2793            }
2794          },
2795          lineColor: '#CCE1FF',
2796        },
2797
2798        yAxis: {
2799          gridLineColor : 'rgba(204,225,255,.5)',
2800          labels: {
2801            align: 'left',
2802            x: 5,
2803            y: 3,
2804            style : {
2805              color: '#8794A0'
2806            },
2807            enabled : true
2808          },
2809          showLastLabel: true,
2810                           tickPixelInterval: 40,
2811
2812        },
2813
2814        series : [
2815              {
2816      name : 'Backlog Linux Builds for Open Source projects',
2817      data : metricDataPoints['5t9vf2rrkm79'],
2818      tooltip: {
2819        valueSuffix: ' jobs'
2820      },
2821      enableMouseTracking : ($(window).outerWidth() > 480) && true
2822    }
2823
2824        ],
2825
2826        tooltip: {
2827          borderWidth: 0,
2828          enabled: ($(window).outerWidth() > 480) && true,
2829          headerFormat: "<span style='font-size: 10px'>{point.key}  </span>",
2830          hideDelay: 300,
2831          pointFormat: "<span style='color:{point.color}'>●</span>  <b>{point.y}</b><br/>",
2832          positioner: function() { return {x: 0, y: 0 }; },
2833          shadow: false,
2834          shape: "square",
2835          split: false
2836        }
2837      });
2838
2839          });
2840      }
2841
2842      var $timePeriodToggles = HRB.utils.djshook('data-time-period-toggle');
2843
2844      SP.currentPage.activeTimePeriodToggle = function(period) {
2845        $timePeriodToggles.removeClass('active');
2846        $timePeriodToggles.filter('[data-time-period="' + period + '"]').addClass('active');
2847      }
2848
2849      SP.currentPage.getAndDisplayInitialChartData = function() {
2850        if (window.location.hash == '#week') {
2851          SP.currentPage.getDataForTimePeriod('week');
2852          SP.currentPage.activeTimePeriodToggle('week');
2853        }
2854        else if (window.location.hash == '#month') {
2855          SP.currentPage.getDataForTimePeriod('month');
2856          SP.currentPage.activeTimePeriodToggle('month');
2857        }
2858        else {
2859          SP.currentPage.getDataForTimePeriod('day');
2860          SP.currentPage.activeTimePeriodToggle('day');
2861        }
2862      }
2863
2864      $timePeriodToggles.on('click', function() {
2865        var newPeriod = $(this).attr('data-time-period');
2866
2867        SP.currentPage.activeTimePeriodToggle(newPeriod);
2868        SP.currentPage.getDataForTimePeriod(newPeriod);
2869        window.location.hash = newPeriod;
2870
2871        return false;
2872      });
2873
2874      SP.currentPage.getAndDisplayInitialChartData();
2875    })
2876    //]]>
2877  </script>
2877
2878
2879
2880
2881      
2881<script>
2882  /** INITIALIZATION **/
2883  var recaptchaIds = {}
2884
2885  // Unfortunately there's no unique selectors on the parent divs that recaptcha adds. The first unique selector
2886  // is the iframe rendered 2 levels deep. So this waits until the iframes are added to the page, then finds
2887  // the parent div and sets the z index so that it'll render above our modals & dropdowns from the start.
2888  function setZIndex(captchaCount, startTime) {
2889    // bail after 10s just in case so we don't do this forever if something whaky happens
2890    if (new Date() - startTime > 10000) {
2891      return;
2892    }
2893
2894    var iframes = document.querySelectorAll('iframe[title="recaptcha challenge"]');
2895    if (iframes.length != captchaCount) {
2896      setTimeout(function() {
2897        setZIndex(captchaCount, startTime);
2898      }, 500);
2899    }
2900
2901    for (var i = 0; i < iframes.length; i++) {
2902      // incident subscribe modal is 1050, so this has to be above that
2903      iframes[i].parentElement.parentElement.style.zIndex = "1100";
2904    }
2905  }
2906
2907  function updateCaptchaIframeTitle(captchaCount, startTime, updates=0) {
2908
2909    if (new Date() - startTime > 10000 || captchaCount === updates) {
2910      return;
2911    }
2912    var iframesWithTitle = document.querySelectorAll('iframe[title="recaptcha challenge expires in two minutes"]');
2913
2914    if (iframesWithTitle.length != captchaCount) {
2915      setTimeout(function() {
2916        updateCaptchaIframeTitle(captchaCount, startTime, iframesWithTitle.length + updates);
2917      }, 500);
2918    }
2919
2920    for (var i = 0; i < iframesWithTitle.length; i++) {
2921      iframesWithTitle[i].title = "recaptcha";
2922    }
2923  }
2924
2925  function addIncidentCaptcha() {
2926    var incidentCaptcha = document.createElement('div');
2927    incidentCaptcha.setAttribute('id', 'subscribe-incident-recaptcha');
2928    incidentCaptcha.setAttribute('class', 'g-recaptcha');
2929    incidentCaptcha.setAttribute('data-sitekey', '6LcZ-b0UAAAAAENi956aWzynTT2ZJ80dGU3F80Op');
2930    incidentCaptcha.setAttribute('data-callback', 'submitIncidentSubscriberSuccess');
2931    incidentCaptcha.setAttribute('data-error-callback', 'submitIncidentSubscriberError');
2932    incidentCaptcha.setAttribute('data-size', 'invisible');
2933    document.body.appendChild(incidentCaptcha);
2934    var incidentCode = document.createElement('input');
2935    incidentCode.setAttribute('type', 'hidden');
2936    incidentCode.setAttribute('id', 'submit_incident_code');
2937    document.body.appendChild(incidentCode);
2938  }
2939
2940  var onloadCallback = function() {
2941    // if there is an incident, then add incident captcha element
2942    if (document.getElementsByClassName('modal-open-incident-subscribe').length > 0) {
2943      addIncidentCaptcha();
2944    }
2945
2946    var captchas = document.getElementsByClassName("g-recaptcha");
2947
2948    for(var i = 0; i < captchas.length; i++) {
2949      var elId = captchas[i].id;
2950      recaptchaIds[elId] = grecaptcha.enterprise.render(elId);
2951    }
2952
2953    setZIndex(captchas.length, new Date());
2954    updateCaptchaIframeTitle(captchas.length, new Date());
2955  }
2956
2957
2958  /** SUBSCRIBE DROPDOWN */
2959
2960  // callbacks for captcha success
2961  function submitNewSubscriber(type, error) {
2962    if (error) document.querySelector('#subscribe-form-' + type + ' #captcha_error').value = 'true';
2963
2964    document.getElementById('subscribe-form-' + type).dispatchEvent(new Event('submit', {bubbles: true, cancelable: true}));
2965    grecaptcha.enterprise.reset(recaptchaIds['subscribe-btn-' + type]);
2966  }
2967  function submitNewEmailSubscriber(token) {
2968    submitNewSubscriber('email');
2969  }
2970  function submitNewSmsSubscriber(token) {
2971    submitNewSubscriber('sms');
2972  }
2973  function submitNewWebhookSubscriber(token) {
2974    submitNewSubscriber('webhook');
2975  }
2976  function submitIncidentSubscriber(token, error, incidentCodeOverride) {
2977    var incidentCode = incidentCodeOverride;
2978    if (!incidentCode) {
2979      var incidentCodeEl = document.getElementById('submit_incident_code');
2980      incidentCode = incidentCodeEl && incidentCodeEl.value;
2981    }
2982    var incidentForm = incidentCode && document.getElementById('subscribe-form-' + incidentCode);
2983    if (!incidentForm) {
2984      return;
2985    }
2986
2987    var captchaError = incidentForm.querySelector('input[name="captcha_error"]');
2988    var recaptchaResponse = incidentForm.querySelector('input[name="g-recaptcha-response"]');
2989    if (captchaError) {
2990      captchaError.value = error;
2991    }
2992    if (recaptchaResponse) {
2993      recaptchaResponse.value = token;
2994    }
2995    incidentForm.dispatchEvent(new Event('submit', {bubbles: true, cancelable: true}));
2996    if (window.grecaptcha && grecaptcha.enterprise && recaptchaIds['subscribe-incident-recaptcha'] != null) {
2997      grecaptcha.enterprise.reset(recaptchaIds['subscribe-incident-recaptcha']);
2998    }
2999  }
3000  function submitIncidentSubscriberSuccess(token) {
3001    submitIncidentSubscriber(token, 'false');
3002  }
3003
3004  // callbacks if we get captcha network errors
3005  function emailSubscriberCaptchaError(token) {
3006    submitNewSubscriber('email', true);
3007  }
3008  function smsSubscriberCaptchaError(token) {
3009    submitNewSubscriber('sms', true);
3010  }
3011  function webhookSubscriberCaptchaError(token) {
3012    submitNewSubscriber('webhook', true);
3013  }
3014  function submitIncidentSubscriberError(token) {
3015    submitIncidentSubscriber(token, 'true');
3016  }
3017
3018  // tracking clicks
3019  ['email', 'sms', 'webhook'].forEach(function(type) {
3020    var el = document.getElementById('subscribe-btn-' + type);
3021    el && el.addEventListener("click", function() {
3022      $.ajax({
3023        type: "POST",
3024        url: "/subscriptions/track_attempt",
3025        data: {
3026          type: type
3027        }
3028      })
3029    })
3030  })
3031
3032  // form submission success callbacks
3033  $('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){
3034    if (data.type === 'success') {
3035      SP.currentPage.updatesDropdown.hide();
3036      var emailField = document.getElementById('email');
3037      if (emailField) {
3038        emailField.value = '';
3039      }
3040    }
3041  });
3042  $('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){
3043    if (data.type === 'success' && data.otp_flow !== true) {
3044      SP.currentPage.updatesDropdown.hide();
3045      var phoneField = document.getElementById('phone-number');
3046      if (phoneField) {
3047        phoneField.value = '';
3048      }
3049    }
3050  });
3051  $('#subscribe-form-webhook').on('ajax:success', function(e, data, status, xhr){
3052    if (data.type === 'success') {
3053      SP.currentPage.updatesDropdown.hide();
3054      document.getElementById('endpoint-webhooks').value = '';
3055      document.getElementById('email-webhooks').value = '';
3056    }
3057  });
3058
3059  $('a.subscribe').on('click', function() {
3060    document.body.style.overflow = "hidden";
3061    document.body.style.height = "100vh";
3062  });
3063
3064  $('div.modal-open-incident-subscribe').on('hidden', function(){
3065    document.body.style.overflow = "";
3066    document.body.style.height = "";
3067  });
3068
3069  function submitCaptchaIncidentSubscribe(event) {
3070    var incidentCode = event.target.id.split('-')[2];
3071    event.preventDefault();
3072
3073    $.ajax({
3074      type: "POST",
3075      url: "/subscriptions/track_attempt",
3076      data: {
3077        type: 'incident'
3078      }
3079    })
3080
3081    var incidentCodeField = document.getElementById('submit_incident_code');
3082    if (incidentCodeField) {
3083      incidentCodeField.value = incidentCode;
3084    }
3085
3086    // Recaptcha's onloadCallback is what creates #submit_incident_code and the
3087    // widget id. If the enterprise.js script is blocked (ad blockers, CI url
3088    // blacklist), execute() and .value on a null node throw and the subscribe
3089    // click never reaches the server.
3090    var recaptchaId = recaptchaIds['subscribe-incident-recaptcha'];
3091    if (window.grecaptcha && grecaptcha.enterprise && typeof grecaptcha.enterprise.execute === 'function' && recaptchaId != null) {
3092      grecaptcha.enterprise.execute(recaptchaId);
3093    } else {
3094      submitIncidentSubscriber('', 'true', incidentCode);
3095    }
3096  }
3097</script>
vendor: 135 bytes, lines 3097-3103
3097
3098
3099<script src='https://www.recaptcha.net/recaptcha/enterprise.js?onload=onloadCallback&render=explicit' async defer></script>
3100
3101
3102    
3103  
3103<script src="https://dka575ofm4ao0.cloudfront.net/packs/common-b57e85f6a60348cdd566.chunk.js"></script>
3103
3104  
3104<script src="https://dka575ofm4ao0.cloudfront.net/packs/globals-79d49f8cfe179f020629.chunk.js"></script>
3104
3105
3106    
3106<script src="https://dka575ofm4ao0.cloudfront.net/packs/runtime-e9fe27ac357824763c7d.js"></script>
3106
3107    
3108    
3109
3110
3111    
3111<script>
3112  window.addEventListener('load', function () {
3113    const urlParams = new URLSearchParams(window.location.search);
3114    const messageToken = urlParams.get('slack_message_token');
3115    const channelName = escape(urlParams.get('channel_name'));
3116
3117    if(!!messageToken) {
3118      switch(messageToken) {
3119        case 'slack_auth_error':
3120          HRB.utils.notify('The Slack authorization attempt was unsuccessful. Try again.', {cssClass:'error'});
3121          break;
3122        case 'subscribers_disabled_error':
3123          HRB.utils.notify('Slack subscriptions are not enabled on this page.', {cssClass:'error'});
3124          break;
3125        case 'direct_message_channel_error':
3126          HRB.utils.notify('Subscriptions aren’t supported in direct messages. Try subscribing again and choose a channel instead.', {cssClass:'error'});
3127          break
3128        case 'duplicate_error':
3129          HRB.utils.notify("You're already subscribed to get Slack notifications in that channel.", {cssClass:'error'});
3130          break;
3131        case 'duplicate_private_channel_error':
3132          HRB.utils.notify(`You're already subscribed to get Slack notifications in #${channelName}. Invite the @Statuspage app to that channel to start getting status updates.`, {cssClass: 'error'});
3133          break;
3134        case 'default_success':
3135          HRB.utils.notify("You're now subscribed to get Statuspage updates in Slack!", {cssClass:'success'});
3136          break;
3137        case 'private_channel_success':
3138          HRB.utils.notify(`IMPORTANT: Invite the @Statuspage app to your Slack channel #${channelName} to start getting status updates.`, {cssClass:'success'});
3139          break;
3140      }
3141    }
3142  });
3143</script>
3143
3144
3145    
3146<!-- FOR FLASH NOTICES -->
3147
3148<!-- FOR ERROR -->
3149
3150
3151    
3151<script>
3152  $(function() {
3153    var $link = $('<span class="color-secondary powered-by"><a class="color-secondary" target="_blank" rel="noopener noreferrer nofollow" href="https://www.atlassian.com/software/statuspage?utm_campaign=www.traviscistatus.com&amp;utm_content=SP-notifications&amp;utm_medium=powered-by&amp;utm_source=inapp">Powered by Atlassian Statuspage</a></span>');
3154
3155  	var setPoweredByStyles = function() {
3156  		if (!$('.powered-by').length) {
3157  			$link.appendTo($('.page-footer'))
3158  		}
3159  		$('.powered-by').attr('style', 'display: inline !important; visibility:visible !important; opacity: 1 !important; position:static !important; text-indent:0px !important; transform:scale(1) !important');
3160  	}
3161
3162  	setInterval(setPoweredByStyles, 1000);
3163  });
3164</script>
3164
3165
3166
3167
3168
3169
3170  </body>
3171</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.