Files
nexus/sreweekly/articles/350/03-buildkite-elevated-error-rates.html
2026-09-12 17:23:01 +08:00

1689 lines
83 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- force IE browsers in compatibility mode to use their most aggressive rendering engine -->
<meta charset="utf-8">
<title>Buildkite Status - Elevated error rates</title>
<meta name="description" content="Buildkite&#39;s Status Page - Elevated error rates.">
<!-- Mobile viewport optimization -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
<!-- Time this page was rendered - http://purl.org/dc/terms/issued -->
<meta name="issued" content="1789191093">
<!-- Mobile IE allows us to activate ClearType technology for smoothing fonts for easy reading -->
<meta http-equiv="cleartype" content="on">
<!-- Atlassian Sans & Mono Fonts -->
<link
rel="preconnect"
href="https://ds-cdn.prod-east.frontend.public.atl-paas.net" />
<link
rel="preload"
href="https://ds-cdn.prod-east.frontend.public.atl-paas.net/assets/fonts/atlassian-sans/v3/AtlassianSans-latin.woff2"
as="font" type="font/woff2" crossorigin />
<link
rel="preload"
href="https://ds-cdn.prod-east.frontend.public.atl-paas.net/assets/font-rules/v5/atlassian-fonts.css"
as="style" crossorigin />
<style>
/* Dynamic Font Stack based on Feature Flag */
/* Using Atlassian Sans & Mono */
:root {
--font-stack-a: "Atlassian Sans", "Helvetica Neue", Helvetica, Arial, Sans-Serif;
--font-stack-b: "Atlassian Mono", "SFMono-Medium", "SF Mono", "Segoe UI Mono", "Roboto Mono", "Ubuntu Mono", Menlo, Consolas, Courier, monospace;
}
</style>
<link rel="shortcut icon" type="image/x-icon" href="//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/1292/Buildkite_Favicon-ea320bac-dee8-4814-bbd3-8cffc75e7420.png" />
<link rel="shortcut icon" href='//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/1292/Buildkite_Favicon-ea320bac-dee8-4814-bbd3-8cffc75e7420.png'>
<link rel="alternate" type="application/atom+xml" href="https://www.buildkitestatus.com/history.atom" title="Buildkite Status History - Atom Feed">
<link rel="alternate" type="application/rss+xml" href="https://www.buildkitestatus.com/history.rss" title="Buildkite Status History - RSS Feed">
<!-- Canonical Link to ensure that only the custom domain is indexed when present -->
<link rel="canonical" href="http://www.buildkitestatus.com/incidents/m8f0dnxtmjbz">
<meta name="_globalsign-domain-verification" content="y_VzfckMy4iePo5oDJNivyYIjh8LffYa4jzUndm_bZ"/>
<link rel="alternate" type="application/atom+xml" title="ATOM" href="https://www.buildkitestatus.com/history.atom" />
<!-- Le styles -->
<link rel="stylesheet" media="screen" href="https://dka575ofm4ao0.cloudfront.net/packs/0.6d587e2c8ae0df459ecd.css" />
<link rel="stylesheet" media="all" href="https://dka575ofm4ao0.cloudfront.net/assets/status/status_manifest-3975cac43f498cd81d991d1abc986307c014f9c6ec29a9abfeb3b0882674850a.css" />
<script src="https://dka575ofm4ao0.cloudfront.net/assets/jquery-3.5.1.min-729e416557a365062a8a20f0562f18aa171da57298005d392312670c706c68de.js"></script>
<script>
window.pageColorData = {"blue":"#0033FF","border":"#DDDDDD","body_background":"#FFFFFF","font":"#333333","graph":"#333333","green":"#00BE13","light_font":"#767676","link":"#4B19D5","orange":"#FF851B","red":"#F83F23","yellow":"#FFBA11","no_data":"#C2CACE"};
</script>
<style>
/* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */
body,
.layout-content.status.status-api .section .example-container .example-opener .color-secondary,
.grouped-items-selector,
.layout-content.status.status-full-history .history-nav a.current,
div[id^="subscribe-modal"] .modal-footer,
div[id^="subscribe-modal"],
div[id^="updates-dropdown"] .updates-dropdown-section,
#uptime-tooltip .tooltip-box {
background-color:#FFFFFF;
}
#uptime-tooltip .pointer-container .pointer-smaller {
border-bottom-color:#FFFFFF;
}
/* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */
body.status,
.color-primary,
.color-primary:hover,
.layout-content.status-index .status-day .update-title.impact-none a,
.layout-content.status-index .status-day .update-title.impact-none a:hover,
.layout-content.status-index .timeframes-container .timeframe.active,
.layout-content.status-full-history .month .incident-container .impact-none,
.layout-content.status.status-index .incidents-list .incident-title.impact-none a,
.incident-history .impact-none,
.layout-content.status .grouped-items-selector.inline .grouped-item.active,
.layout-content.status.status-full-history .history-nav a.current,
.layout-content.status.status-full-history .history-nav a:not(.current):hover,
div[id^="subscribe-modal"] .modal-header .close,
.grouped-item-label,
#uptime-tooltip .tooltip-box .tooltip-content .related-events .related-event a.related-event-link {
color:#333333;
}
.layout-content.status.status-index .components-statuses .component-container .name {
color:#333333;
color:rgba(51,51,51,.8);
}
/* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */
small,
.layout-content.status .table-row .date,
.color-secondary,
.layout-content.status .grouped-items-selector.inline .grouped-item,
.layout-content.status.status-full-history .history-footer .pagination a.disabled,
.layout-content.status.status-full-history .history-nav a,
#uptime-tooltip .tooltip-box .tooltip-content .related-events #related-event-header {
color:#767676;
}
/* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */
body.status .layout-content.status .border-color,
hr,
.tooltip-base,
.markdown-display table,
div[id^="subscribe-modal"],
#uptime-tooltip .tooltip-box {
border-color:#DDDDDD;
}
div[id^="subscribe-modal"] .modal-footer,
.markdown-display table td {
border-top-color:#DDDDDD;
}
.markdown-display table td + td, .markdown-display table th + th {
border-left-color:#DDDDDD;
}
div[id^="subscribe-modal"] .modal-header,
#uptime-tooltip .pointer-container .pointer-larger {
border-bottom-color:#DDDDDD;
}
#uptime-tooltip .tooltip-box .outage-field {
/*
Generate the background-color for the outage-field from the css_body_background_color and css_border_color.
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
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.
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).
*/
background-color: rgba(221,221,221,0.31);
/*
outage-field border-color alpha is inverse to the luminosity of css_body_background_color.
That is to say, with a default white background this border is transparent, but on a black background, it's opaque css_border_color.
*/
border-color: rgba(221,221,221,0.0);
}
/* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */
.layout-content.status.status-index .status-day .update-title.impact-critical a,
.layout-content.status.status-index .status-day .update-title.impact-critical a:hover,
.layout-content.status.status-index .page-status.status-critical,
.layout-content.status.status-index .unresolved-incident.impact-critical .incident-title,
.flat-button.background-red {
background-color:#F83F23;
}
.layout-content.status-index .components-statuses .component-container.status-red:after,
.layout-content.status-full-history .month .incident-container .impact-critical,
.layout-content.status-incident .incident-name.impact-critical,
.layout-content.status.status-index .incidents-list .incident-title.impact-critical a,
.status-red .icon-indicator,
.incident-history .impact-critical,
.components-container .component-inner-container.status-red .component-status,
.components-container .component-inner-container.status-red .icon-indicator {
color:#F83F23;
}
.layout-content.status.status-index .unresolved-incident.impact-critical .updates {
border-color:#F83F23;
}
/* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */
.layout-content.status.status-index .status-day .update-title.impact-major a,
.layout-content.status.status-index .status-day .update-title.impact-major a:hover,
.layout-content.status.status-index .page-status.status-major,
.layout-content.status.status-index .unresolved-incident.impact-major .incident-title {
background-color:#FF851B;
}
.layout-content.status-index .components-statuses .component-container.status-orange:after,
.layout-content.status-full-history .month .incident-container .impact-major,
.layout-content.status-incident .incident-name.impact-major,
.layout-content.status.status-index .incidents-list .incident-title.impact-major a,
.status-orange .icon-indicator,
.incident-history .impact-major,
.components-container .component-inner-container.status-orange .component-status,
.components-container .component-inner-container.status-orange .icon-indicator {
color:#FF851B;
}
.layout-content.status.status-index .unresolved-incident.impact-major .updates {
border-color:#FF851B;
}
/* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */
.layout-content.status.status-index .status-day .update-title.impact-minor a,
.layout-content.status.status-index .status-day .update-title.impact-minor a:hover,
.layout-content.status.status-index .page-status.status-minor,
.layout-content.status.status-index .unresolved-incident.impact-minor .incident-title,
.layout-content.status.status-index .scheduled-incidents-container .tab {
background-color:#FFBA11;
}
.layout-content.status-index .components-statuses .component-container.status-yellow:after,
.layout-content.status-full-history .month .incident-container .impact-minor,
.layout-content.status-incident .incident-name.impact-minor,
.layout-content.status.status-index .incidents-list .incident-title.impact-minor a,
.status-yellow .icon-indicator,
.incident-history .impact-minor,
.components-container .component-inner-container.status-yellow .component-status,
.components-container .component-inner-container.status-yellow .icon-indicator,
.layout-content.status.manage-subscriptions .confirmation-infobox .fa {
color:#FFBA11;
}
.layout-content.status.status-index .unresolved-incident.impact-minor .updates,
.layout-content.status.status-index .scheduled-incidents-container {
border-color:#FFBA11;
}
/* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */
.layout-content.status.status-index .status-day .update-title.impact-maintenance a,
.layout-content.status.status-index .status-day .update-title.impact-maintenance a:hover,
.layout-content.status.status-index .page-status.status-maintenance,
.layout-content.status.status-index .unresolved-incident.impact-maintenance .incident-title,
.layout-content.status.status-index .scheduled-incidents-container .tab {
background-color:#0033FF;
}
.layout-content.status-index .components-statuses .component-container.status-blue:after,
.layout-content.status-full-history .month .incident-container .impact-maintenance,
.layout-content.status-incident .incident-name.impact-maintenance,
.layout-content.status.status-index .incidents-list .incident-title.impact-maintenance a,
.status-blue .icon-indicator,
.incident-history .impact-maintenance,
.components-container .component-inner-container.status-blue .component-status,
.components-container .component-inner-container.status-blue .icon-indicator {
color:#0033FF;
}
.layout-content.status.status-index .unresolved-incident.impact-maintenance .updates,
.layout-content.status.status-index .scheduled-incidents-container {
border-color:#0033FF;
}
/* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */
.layout-content.status.status-index .page-status.status-none {
background-color:#00BE13;
}
.layout-content.status-index .components-statuses .component-container.status-green:after,
.status-green .icon-indicator,
.components-container .component-inner-container.status-green .component-status,
.components-container .component-inner-container.status-green .icon-indicator {
color:#00BE13;
}
/* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */
a,
a:hover,
.layout-content.status-index .page-footer span a:hover,
.layout-content.status-index .timeframes-container .timeframe:not(.active):hover,
.layout-content.status-incident .subheader a:hover {
color:#4B19D5;
}
.flat-button,
.masthead .updates-dropdown-container .show-updates-dropdown,
.layout-content.status-full-history .show-filter.open {
background-color:#4B19D5;
}
/* CUSTOM COLOR OVERRIDES FOR UPTIME SHOWCASE */
.components-section .components-uptime-link {
color: #767676;
}
.layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item {
color: #767676;
opacity: 1;
}
.layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item.light {
color: #767676;
opacity: 1;
}
.layout-content.status .shared-partial.uptime-90-days-wrapper .legend .spacer {
background: #767676;
opacity: 1;
}
</style>
<!-- custom css -->
<link rel="stylesheet" type="text/css" href="//dka575ofm4ao0.cloudfront.net/page_display_customizations-custom_css_externals/101/external20230719-46-phga.css">
<!-- polyfills -->
<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js"></script>
<!-- Le HTML5 shim -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- injection for static -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="buildkitestatus">
<meta name="twitter:creator" content="buildkitestatus">
<meta name="robots" content="noindex,nofollow">
<meta property="og:type" content="article">
<meta property="og:url" content="http://www.buildkitestatus.com/incidents/m8f0dnxtmjbz">
<meta property="og:image" content="https://dka575ofm4ao0.cloudfront.net/pages-twitter_logos/original/1292/Frame_1240-111f2258-e913-4389-acf7-4e0cc17374a1.png">
<meta property="og:title" content="Elevated error rates">
<meta property="og:description">
</head>
<body class="status incident status-none sp-a11y-status-focus-visibility a11y-focus-indicators">
<style>
/* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */
body,
.layout-content.status.status-api .section .example-container .example-opener .color-secondary,
.grouped-items-selector,
.layout-content.status.status-full-history .history-nav a.current,
div[id^="subscribe-modal"] .modal-footer,
div[id^="subscribe-modal"],
div[id^="updates-dropdown"] .updates-dropdown-section,
#uptime-tooltip .tooltip-box {
background-color:#FFFFFF;
}
#uptime-tooltip .pointer-container .pointer-smaller {
border-bottom-color:#FFFFFF;
}
/* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */
body.status,
.color-primary,
.color-primary:hover,
.layout-content.status-index .status-day .update-title.impact-none a,
.layout-content.status-index .status-day .update-title.impact-none a:hover,
.layout-content.status-index .timeframes-container .timeframe.active,
.layout-content.status-full-history .month .incident-container .impact-none,
.layout-content.status.status-index .incidents-list .incident-title.impact-none a,
.incident-history .impact-none,
.layout-content.status .grouped-items-selector.inline .grouped-item.active,
.layout-content.status.status-full-history .history-nav a.current,
.layout-content.status.status-full-history .history-nav a:not(.current):hover,
div[id^="subscribe-modal"] .modal-header .close,
.grouped-item-label,
#uptime-tooltip .tooltip-box .tooltip-content .related-events .related-event a.related-event-link {
color:#333333;
}
.layout-content.status.status-index .components-statuses .component-container .name {
color:#333333;
color:rgba(51,51,51,.8);
}
/* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */
small,
.layout-content.status .table-row .date,
.color-secondary,
.layout-content.status .grouped-items-selector.inline .grouped-item,
.layout-content.status.status-full-history .history-footer .pagination a.disabled,
.layout-content.status.status-full-history .history-nav a,
#uptime-tooltip .tooltip-box .tooltip-content .related-events #related-event-header {
color:#767676;
}
/* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */ /* BORDER COLOR */
body.status .layout-content.status .border-color,
hr,
.tooltip-base,
.markdown-display table,
div[id^="subscribe-modal"],
#uptime-tooltip .tooltip-box {
border-color:#DDDDDD;
}
div[id^="subscribe-modal"] .modal-footer,
.markdown-display table td {
border-top-color:#DDDDDD;
}
.markdown-display table td + td, .markdown-display table th + th {
border-left-color:#DDDDDD;
}
div[id^="subscribe-modal"] .modal-header,
#uptime-tooltip .pointer-container .pointer-larger {
border-bottom-color:#DDDDDD;
}
#uptime-tooltip .tooltip-box .outage-field {
/*
Generate the background-color for the outage-field from the css_body_background_color and css_border_color.
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
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.
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).
*/
background-color: rgba(221,221,221,0.31);
/*
outage-field border-color alpha is inverse to the luminosity of css_body_background_color.
That is to say, with a default white background this border is transparent, but on a black background, it's opaque css_border_color.
*/
border-color: rgba(221,221,221,0.0);
}
/* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */
.layout-content.status.status-index .status-day .update-title.impact-critical a,
.layout-content.status.status-index .status-day .update-title.impact-critical a:hover,
.layout-content.status.status-index .page-status.status-critical,
.layout-content.status.status-index .unresolved-incident.impact-critical .incident-title,
.flat-button.background-red {
background-color:#F83F23;
}
.layout-content.status-index .components-statuses .component-container.status-red:after,
.layout-content.status-full-history .month .incident-container .impact-critical,
.layout-content.status-incident .incident-name.impact-critical,
.layout-content.status.status-index .incidents-list .incident-title.impact-critical a,
.status-red .icon-indicator,
.incident-history .impact-critical,
.components-container .component-inner-container.status-red .component-status,
.components-container .component-inner-container.status-red .icon-indicator {
color:#F83F23;
}
.layout-content.status.status-index .unresolved-incident.impact-critical .updates {
border-color:#F83F23;
}
/* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */
.layout-content.status.status-index .status-day .update-title.impact-major a,
.layout-content.status.status-index .status-day .update-title.impact-major a:hover,
.layout-content.status.status-index .page-status.status-major,
.layout-content.status.status-index .unresolved-incident.impact-major .incident-title {
background-color:#FF851B;
}
.layout-content.status-index .components-statuses .component-container.status-orange:after,
.layout-content.status-full-history .month .incident-container .impact-major,
.layout-content.status-incident .incident-name.impact-major,
.layout-content.status.status-index .incidents-list .incident-title.impact-major a,
.status-orange .icon-indicator,
.incident-history .impact-major,
.components-container .component-inner-container.status-orange .component-status,
.components-container .component-inner-container.status-orange .icon-indicator {
color:#FF851B;
}
.layout-content.status.status-index .unresolved-incident.impact-major .updates {
border-color:#FF851B;
}
/* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */
.layout-content.status.status-index .status-day .update-title.impact-minor a,
.layout-content.status.status-index .status-day .update-title.impact-minor a:hover,
.layout-content.status.status-index .page-status.status-minor,
.layout-content.status.status-index .unresolved-incident.impact-minor .incident-title,
.layout-content.status.status-index .scheduled-incidents-container .tab {
background-color:#FFBA11;
}
.layout-content.status-index .components-statuses .component-container.status-yellow:after,
.layout-content.status-full-history .month .incident-container .impact-minor,
.layout-content.status-incident .incident-name.impact-minor,
.layout-content.status.status-index .incidents-list .incident-title.impact-minor a,
.status-yellow .icon-indicator,
.incident-history .impact-minor,
.components-container .component-inner-container.status-yellow .component-status,
.components-container .component-inner-container.status-yellow .icon-indicator,
.layout-content.status.manage-subscriptions .confirmation-infobox .fa {
color:#FFBA11;
}
.layout-content.status.status-index .unresolved-incident.impact-minor .updates,
.layout-content.status.status-index .scheduled-incidents-container {
border-color:#FFBA11;
}
/* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */
.layout-content.status.status-index .status-day .update-title.impact-maintenance a,
.layout-content.status.status-index .status-day .update-title.impact-maintenance a:hover,
.layout-content.status.status-index .page-status.status-maintenance,
.layout-content.status.status-index .unresolved-incident.impact-maintenance .incident-title,
.layout-content.status.status-index .scheduled-incidents-container .tab {
background-color:#0033FF;
}
.layout-content.status-index .components-statuses .component-container.status-blue:after,
.layout-content.status-full-history .month .incident-container .impact-maintenance,
.layout-content.status-incident .incident-name.impact-maintenance,
.layout-content.status.status-index .incidents-list .incident-title.impact-maintenance a,
.status-blue .icon-indicator,
.incident-history .impact-maintenance,
.components-container .component-inner-container.status-blue .component-status,
.components-container .component-inner-container.status-blue .icon-indicator {
color:#0033FF;
}
.layout-content.status.status-index .unresolved-incident.impact-maintenance .updates,
.layout-content.status.status-index .scheduled-incidents-container {
border-color:#0033FF;
}
/* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */
.layout-content.status.status-index .page-status.status-none {
background-color:#00BE13;
}
.layout-content.status-index .components-statuses .component-container.status-green:after,
.status-green .icon-indicator,
.components-container .component-inner-container.status-green .component-status,
.components-container .component-inner-container.status-green .icon-indicator {
color:#00BE13;
}
/* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */ /* CSS LINK COLOR */
a,
a:hover,
.layout-content.status-index .page-footer span a:hover,
.layout-content.status-index .timeframes-container .timeframe:not(.active):hover,
.layout-content.status-incident .subheader a:hover {
color:#4B19D5;
}
.flat-button,
.masthead .updates-dropdown-container .show-updates-dropdown,
.layout-content.status-full-history .show-filter.open {
background-color:#4B19D5;
}
/* CUSTOM COLOR OVERRIDES FOR UPTIME SHOWCASE */
.components-section .components-uptime-link {
color: #767676;
}
.layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item {
color: #767676;
opacity: 1;
}
.layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item.light {
color: #767676;
opacity: 1;
}
.layout-content.status .shared-partial.uptime-90-days-wrapper .legend .spacer {
background: #767676;
opacity: 1;
}
</style>
<div class="layout-content status status-incident">
<div class="container">
<div class="page-title">
<h1 class="color-primary incident-name whitespace-pre-wrap impact-major">Elevated error rates</h1>
<div class="font-largest color-secondary subheader ">
Incident
Report for <a class="color-secondary" href="/">Buildkite</a>
</div>
</div>
<div class="incident-updates-container">
<!-- postmortem if it's published -->
<div class="row update-row">
<h2 class="update-title span3 font-large">
Postmortem
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<div class="markdown-display">
<p><strong>Service Impact</strong></p>
<p>Around 2022-11-19 13:00 UTC, a small subset of agents disconnected and failed to reconnect again. From 2022-11-21 02:35 to 03:10 UTC, high Agent API error rates prevented agents from successfully processing jobs. After this point, newly connected agents could successfully execute jobs, but older agents still couldn&#39;t reconnect. From 2022-11-21 05:54 UTC, older agents were successfully reconnected.</p>
<p><strong>Incident Summary</strong></p>
<p>Last Wednesday we began backfilling a new table that provides better tracking of automatic retry rules for build jobs. A Redis <a href="https://redis.io/docs/data-types/sets/">set</a> of IDs was persisted in one of our ElastiCache clusters to track which builds were backfilled. Initial calculations indicated that this set would fit within the memory constraints of the cluster, but as this backfill ran over the weekend it became clear that the calculations were incorrect.</p>
<p>Around 12:00 Saturday (UTC) the Redis shard holding this growing set ran low on memory, and our <a href="https://redis.io/docs/reference/eviction/#eviction-policies"><em>volatile-lru</em> eviction policy</a> began deleting some agent heartbeat state from that shard.</p>
<p>Agents are marked as &quot;lost&quot; after 10 minutes without a heartbeat. A heartbeat from a recently lost agent returns it to “connected”, but after 24 hours the session token is invalidated, resulting in <em>HTTP 401 Unauthorized</em> responses.</p>
<p>During this incident, the eviction of heartbeat state from one shard caused those agents to be considered “last seen” at their registration timestamp. This meant agents connected longer than 24 hours were considered permanently lost, and their tokens considered invalid, resulting in those agents receiving HTTP 401 responses to their API requests. Agents would ideally re-register at this point, but the HTTP 401 wasn’t treated as terminal, so they continued to wait for jobs to be assigned. At this point, the only solution for affected customers was to restart or replace those agents.</p>
<p>On Sunday evening (UTC) the lack of memory of the impacted Redis shard was detected, though it was not having an ongoing impact on our customers&#39; jobs or agents. In order to clear space, we attempted to delete the large Redis set at 2022-11-21 02:35 UTC. The <a href="https://redis.io/commands/del/">DEL</a> command in Redis is O(N) relative to the collection size, and our N was large enough to make the shard unresponsive. This triggered a failover to the replica for that shard, but meanwhile resulted in higher load on our underlying database, which together resulted in the Agent API error rate peaking at 80%. This was the point at which builds stopped successfully executing for the majority of our customers.</p>
<p>We explored options such as dropping the shard or restarting the Redis cluster, but decided to failover to a new, empty Redis cluster. The switch to this new cluster took effect at 2022-11-21 03:10 UTC, and we saw Agent API error rates return to normal levels. From this point, any newly-connected agent could successfully pick up and complete jobs.</p>
<p>Agents were expected to reconnect, but our metrics indicated that wasn’t happening. We eventually found a data inconsistency — the agents were seeing a “connected” state from a Redis session cache, while the state in the database was “lost”. It was unclear at the time how we ended up in this split-brain situation, but until the session cache for these agents expired, they would be unable to reconnect.</p>
<p>In order to speed up their reconnection, we invalidated the entire session cache by incrementing the cache key version, which refreshed the session data for all agents and allowed them to come back online. This process was finished at 2022-11-21 05:54 UTC.</p>
<p>We now believe that the inconsistency between the session cache and the database was a result of the rolling update to the new Redis cluster. The Agent API became functional again once our web nodes were pointed at the cluster, and at this point, we believe that our customers&#39; agents&#39; next heartbeat signals would have resulted in them moving from &quot;lost&quot; to &quot;connected&quot; again – this would have been reflected in both the database and the new cache.</p>
<p>However, at this point, some instances of our background workers would still have been pointed at the old cache, which did not contain any heartbeat records. For the same reason as Saturday morning, the agents were marked as “lost”, which updated both the database and the *old* cache. This is how we ended up with a database that said the agents were lost, and a cache that said they were connected.</p>
<p><strong>How we’re becoming more resilient to issues like this</strong></p>
<p>Our monitoring should have alerted us to the high memory usage in Redis, but a misconfiguration prevented it triggering a notification/pager. This has been resolved.</p>
<p>Agent heartbeats from the past 24 hours should never be evicted from Redis, but by setting a 24 hour expiry they’re stored as “volatile”, meaning the configured <a href="https://redis.io/docs/reference/eviction/#eviction-policies"><em>volatile-lru</em> policy</a> (or any policy other than <em>noeviction</em>) may select them for eviction. Other data in the same cluster does require eviction. We’re exploring separating this into two separate Redis clusters for volatile vs non-volatile data, and configuring the latter with the <em>noeviction</em> policy.</p>
<p>The absence of heartbeat data in Redis, whether caused by eviction or some other event, should be treated as “data missing; unknown last heartbeat” rather than an authoritative “heartbeat never received”, and so should not cause agents to be considered “lost”. This change has been implemented and tested, and will likely ship after a thorough review is completed.</p>
<p>If we need to delete a very large Redis collection in future, we’ll <a href="https://www.memetria.com/blog/deleting-large-sets">do so incrementally</a>, and we’re investigating automated safety checks to that effect, similar to how we <a href="https://github.com/ankane/strong_migrations">safety-check database migrations</a>.</p>
<p>Buildkite Agents were indefinitely retrying API calls when receiving HTTP 401 Unauthorized responses due to no heartbeat data for more than 24 hours, leaving them stuck in a running-but-not-connected state. These agents counted towards capacity in many customers&#39; auto scaling logic, leading to insufficient <em>connected</em> agents to run builds. This will be fixed in a subsequent version of the Buildkite Agent, such that terminal HTTP 401 responses will result in re-registration or termination, self-healing that scenario.</p>
</div>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669353262000"></span>Nov <var data-var='date'>25</var>, <var data-var='year'>2022</var> - <var data-var='time'>05:14</var> UTC
</div>
</div>
</div>
<hr>
<!-- incident updates in reverse order -->
<div class="row update-row">
<h2 class="update-title span3 font-large">
Resolved
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">Error rates have remained at normal levels for some time now. Our monitoring shows that lost agents have been reconnected and are successfully running jobs.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669010987000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>06:09</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Monitoring
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We’ve seen error rates return to normal levels for some time now. Our monitoring shows that lost agents have been reconnected and are successfully running jobs.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669010079000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>05:54</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Update
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">Agents that were previously unresponsive should now be processing jobs again. Our advice to restart agent processes/instances no longer applies, as the issue has been fixed server-side.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669008707000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>05:31</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Update
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We are still in the process of restoring previously connected agents. We recommend cycling your agents by spinning up new ones and removing those experiencing issues in running jobs.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669006726000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>04:58</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Update
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We are in the process of trying to restore the connection to agents that were previously connected. As an interim measure, we recommend that you restart your agent instances</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669005211000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>04:33</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Update
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We believe connected agents may be in a stuck state that is not operational and are continuing to investigate the cause and work on a fix. As an interim measure, we recommend cycling your agent instances to produce new agents</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669003788000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>04:09</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Update
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We have promoted the new redis node to primary. We are now investigating agent connectivity and working to restore service.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669002418000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>03:46</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Update
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We are in the process of promoting the new redis cluster to primary.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669001130000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>03:25</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Identified
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We have identified an issue with our redis cluster and are provisioning a new redis cluster and preparing to roll over.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1669000296000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>03:11</var> UTC
</div>
</div>
</div>
<div class="row update-row">
<h2 class="update-title span3 font-large">
Investigating
</h2>
<div class="update-container span9">
<div class="update-body font-regular">
<span class="whitespace-pre-wrap">We are currently investigating an issue causing elevated error rates and high latency.</span>
</div>
<div class="update-timestamp font-small color-secondary">
Posted <span class="ago" data-datetime-unix="1668999260000"></span>Nov <var data-var='date'>21</var>, <var data-var='year'>2022</var> - <var data-var='time'>02:54</var> UTC
</div>
</div>
</div>
<!-- affected components -->
<div class="components-affected font-small color-secondary border-color">
This incident affected: REST API (REST API) and Web, Agent API.
</div>
</div>
<div class="page-footer border-color font-small">
<a href="/"><span style="font-family:arial">&larr;</span> Current Status</a>
<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.buildkitestatus.com&amp;utm_content=SP-notifications&amp;utm_medium=powered-by&amp;utm_source=inapp">Powered by Atlassian Statuspage</a></span>
</div>
</div>
</div>
<div class="modal hide fade modal-open-incident-subscribe" id="subscribe-modal-m8f0dnxtmjbz" style="display: none"
data-js-hook="incident-subscription-modal" role="dialog" aria-labelledby="incident-subscription-dialog-header"
aria-describedby="incident-subscription-dialog-description" aria-modal="true">
<form class="modal-content" id="subscribe-form-m8f0dnxtmjbz" action="/subscriptions/incident.json" accept-charset="UTF-8" data-remote="true" method="post">
<input type="hidden" name="incident_code" id="incident_code" value="m8f0dnxtmjbz" autocomplete="off" />
<div class="modal-header">
<a href="#" data-dismiss="modal" class="close" data-js-hook="incident-modal-close" aria-label="close" role="button">×</a>
<h1 id="incident-subscription-dialog-header"> Subscribe to Incident </h1>
</div>
<div class="modal-body">
<p style="margin-bottom:25px" id="incident-subscription-dialog-description">
Subscribe to updates for <strong>Elevated error rates</strong> via email and/or text message. You'll receive email notifications when incidents are updated, and text message notifications whenever Buildkite <strong>creates</strong> or <strong>resolves</strong> an incident.
</p>
<div class="control-group">
<label for="email-m8f0dnxtmjbz">VIA EMAIL:</label>
<div class="controls">
<input type="text" name="email" id="email-m8f0dnxtmjbz" data-js-hook="email" class="full-width" />
</div>
</div>
<div class="control-group">
<label class="phone-country-code" for=phone-country-m8f0dnxtmjbz>VIA SMS:</label>
<div class="controls phone-number">
<div class="row">
<div id='phone-number-code-m8f0dnxtmjbz' class="phone-country-wrapper">
<select name="phone_country" id="phone-country-m8f0dnxtmjbz" data-js-hook="phone-country" class="span6 phone-country-dropdown"><option value="af" data-otp-enabled="false" >Afghanistan (+93)</option>
<option value="al" data-otp-enabled="false" >Albania (+355)</option>
<option value="dz" data-otp-enabled="false" >Algeria (+213)</option>
<option value="as" data-otp-enabled="false" >American Samoa (+1)</option>
<option value="ad" data-otp-enabled="false" >Andorra (+376)</option>
<option value="ao" data-otp-enabled="false" >Angola (+244)</option>
<option value="ai" data-otp-enabled="false" >Anguilla (+1)</option>
<option value="ag" data-otp-enabled="false" >Antigua and Barbuda (+1)</option>
<option value="ar" data-otp-enabled="false" >Argentina (+54)</option>
<option value="am" data-otp-enabled="false" >Armenia (+374)</option>
<option value="aw" data-otp-enabled="false" >Aruba (+297)</option>
<option value="au" data-otp-enabled="false" selected>Australia/Cocos/Christmas Island (+61)</option>
<option value="at" data-otp-enabled="false" >Austria (+43)</option>
<option value="az" data-otp-enabled="false" >Azerbaijan (+994)</option>
<option value="bs" data-otp-enabled="false" >Bahamas (+1)</option>
<option value="bh" data-otp-enabled="false" >Bahrain (+973)</option>
<option value="bd" data-otp-enabled="false" >Bangladesh (+880)</option>
<option value="bb" data-otp-enabled="false" >Barbados (+1)</option>
<option value="by" data-otp-enabled="false" >Belarus (+375)</option>
<option value="be" data-otp-enabled="false" >Belgium (+32)</option>
<option value="bz" data-otp-enabled="false" >Belize (+501)</option>
<option value="bj" data-otp-enabled="false" >Benin (+229)</option>
<option value="bm" data-otp-enabled="false" >Bermuda (+1)</option>
<option value="bo" data-otp-enabled="false" >Bolivia (+591)</option>
<option value="ba" data-otp-enabled="false" >Bosnia and Herzegovina (+387)</option>
<option value="bw" data-otp-enabled="false" >Botswana (+267)</option>
<option value="br" data-otp-enabled="false" >Brazil (+55)</option>
<option value="bn" data-otp-enabled="false" >Brunei (+673)</option>
<option value="bg" data-otp-enabled="false" >Bulgaria (+359)</option>
<option value="bf" data-otp-enabled="false" >Burkina Faso (+226)</option>
<option value="bi" data-otp-enabled="false" >Burundi (+257)</option>
<option value="kh" data-otp-enabled="false" >Cambodia (+855)</option>
<option value="cm" data-otp-enabled="false" >Cameroon (+237)</option>
<option value="ca" data-otp-enabled="false" >Canada (+1)</option>
<option value="cv" data-otp-enabled="false" >Cape Verde (+238)</option>
<option value="ky" data-otp-enabled="false" >Cayman Islands (+1)</option>
<option value="cf" data-otp-enabled="false" >Central Africa (+236)</option>
<option value="td" data-otp-enabled="false" >Chad (+235)</option>
<option value="cl" data-otp-enabled="false" >Chile (+56)</option>
<option value="cn" data-otp-enabled="false" >China (+86)</option>
<option value="co" data-otp-enabled="false" >Colombia (+57)</option>
<option value="km" data-otp-enabled="false" >Comoros (+269)</option>
<option value="cg" data-otp-enabled="false" >Congo (+242)</option>
<option value="cd" data-otp-enabled="false" >Congo, Dem Rep (+243)</option>
<option value="cr" data-otp-enabled="false" >Costa Rica (+506)</option>
<option value="hr" data-otp-enabled="false" >Croatia (+385)</option>
<option value="cy" data-otp-enabled="false" >Cyprus (+357)</option>
<option value="cz" data-otp-enabled="false" >Czech Republic (+420)</option>
<option value="dk" data-otp-enabled="false" >Denmark (+45)</option>
<option value="dj" data-otp-enabled="false" >Djibouti (+253)</option>
<option value="dm" data-otp-enabled="false" >Dominica (+1)</option>
<option value="do" data-otp-enabled="false" >Dominican Republic (+1)</option>
<option value="eg" data-otp-enabled="false" >Egypt (+20)</option>
<option value="sv" data-otp-enabled="false" >El Salvador (+503)</option>
<option value="gq" data-otp-enabled="false" >Equatorial Guinea (+240)</option>
<option value="ee" data-otp-enabled="false" >Estonia (+372)</option>
<option value="et" data-otp-enabled="false" >Ethiopia (+251)</option>
<option value="fo" data-otp-enabled="false" >Faroe Islands (+298)</option>
<option value="fj" data-otp-enabled="false" >Fiji (+679)</option>
<option value="fi" data-otp-enabled="false" >Finland/Aland Islands (+358)</option>
<option value="fr" data-otp-enabled="false" >France (+33)</option>
<option value="gf" data-otp-enabled="false" >French Guiana (+594)</option>
<option value="pf" data-otp-enabled="false" >French Polynesia (+689)</option>
<option value="ga" data-otp-enabled="false" >Gabon (+241)</option>
<option value="gm" data-otp-enabled="false" >Gambia (+220)</option>
<option value="ge" data-otp-enabled="false" >Georgia (+995)</option>
<option value="de" data-otp-enabled="false" >Germany (+49)</option>
<option value="gh" data-otp-enabled="false" >Ghana (+233)</option>
<option value="gi" data-otp-enabled="false" >Gibraltar (+350)</option>
<option value="gr" data-otp-enabled="false" >Greece (+30)</option>
<option value="gl" data-otp-enabled="false" >Greenland (+299)</option>
<option value="gd" data-otp-enabled="false" >Grenada (+1)</option>
<option value="gp" data-otp-enabled="false" >Guadeloupe (+590)</option>
<option value="gu" data-otp-enabled="false" >Guam (+1)</option>
<option value="gt" data-otp-enabled="false" >Guatemala (+502)</option>
<option value="gn" data-otp-enabled="false" >Guinea (+224)</option>
<option value="gy" data-otp-enabled="false" >Guyana (+592)</option>
<option value="ht" data-otp-enabled="false" >Haiti (+509)</option>
<option value="hn" data-otp-enabled="false" >Honduras (+504)</option>
<option value="hk" data-otp-enabled="false" >Hong Kong (+852)</option>
<option value="hu" data-otp-enabled="false" >Hungary (+36)</option>
<option value="is" data-otp-enabled="false" >Iceland (+354)</option>
<option value="in" data-otp-enabled="false" >India (+91)</option>
<option value="id" data-otp-enabled="false" >Indonesia (+62)</option>
<option value="iq" data-otp-enabled="false" >Iraq (+964)</option>
<option value="ie" data-otp-enabled="false" >Ireland (+353)</option>
<option value="il" data-otp-enabled="false" >Israel (+972)</option>
<option value="it" data-otp-enabled="false" >Italy (+39)</option>
<option value="jm" data-otp-enabled="false" >Jamaica (+1)</option>
<option value="jp" data-otp-enabled="false" >Japan (+81)</option>
<option value="jo" data-otp-enabled="false" >Jordan (+962)</option>
<option value="ke" data-otp-enabled="false" >Kenya (+254)</option>
<option value="kr" data-otp-enabled="false" >Korea, Republic of (+82)</option>
<option value="xk" data-otp-enabled="false" >Kosovo (+383)</option>
<option value="kw" data-otp-enabled="false" >Kuwait (+965)</option>
<option value="kg" data-otp-enabled="false" >Kyrgyzstan (+996)</option>
<option value="la" data-otp-enabled="false" >Laos (+856)</option>
<option value="lv" data-otp-enabled="false" >Latvia (+371)</option>
<option value="lb" data-otp-enabled="false" >Lebanon (+961)</option>
<option value="ls" data-otp-enabled="false" >Lesotho (+266)</option>
<option value="lr" data-otp-enabled="false" >Liberia (+231)</option>
<option value="ly" data-otp-enabled="false" >Libya (+218)</option>
<option value="li" data-otp-enabled="false" >Liechtenstein (+423)</option>
<option value="lt" data-otp-enabled="false" >Lithuania (+370)</option>
<option value="lu" data-otp-enabled="false" >Luxembourg (+352)</option>
<option value="mo" data-otp-enabled="false" >Macao (+853)</option>
<option value="mk" data-otp-enabled="false" >Macedonia (+389)</option>
<option value="mg" data-otp-enabled="false" >Madagascar (+261)</option>
<option value="mw" data-otp-enabled="false" >Malawi (+265)</option>
<option value="my" data-otp-enabled="false" >Malaysia (+60)</option>
<option value="mv" data-otp-enabled="false" >Maldives (+960)</option>
<option value="ml" data-otp-enabled="false" >Mali (+223)</option>
<option value="mt" data-otp-enabled="false" >Malta (+356)</option>
<option value="mq" data-otp-enabled="false" >Martinique (+596)</option>
<option value="mr" data-otp-enabled="false" >Mauritania (+222)</option>
<option value="mu" data-otp-enabled="false" >Mauritius (+230)</option>
<option value="mx" data-otp-enabled="false" >Mexico (+52)</option>
<option value="mc" data-otp-enabled="false" >Monaco (+377)</option>
<option value="mn" data-otp-enabled="false" >Mongolia (+976)</option>
<option value="me" data-otp-enabled="false" >Montenegro (+382)</option>
<option value="ms" data-otp-enabled="false" >Montserrat (+1)</option>
<option value="ma" data-otp-enabled="false" >Morocco/Western Sahara (+212)</option>
<option value="mz" data-otp-enabled="false" >Mozambique (+258)</option>
<option value="na" data-otp-enabled="false" >Namibia (+264)</option>
<option value="np" data-otp-enabled="false" >Nepal (+977)</option>
<option value="nl" data-otp-enabled="false" >Netherlands (+31)</option>
<option value="nz" data-otp-enabled="false" >New Zealand (+64)</option>
<option value="ni" data-otp-enabled="false" >Nicaragua (+505)</option>
<option value="ne" data-otp-enabled="false" >Niger (+227)</option>
<option value="ng" data-otp-enabled="false" >Nigeria (+234)</option>
<option value="no" data-otp-enabled="false" >Norway (+47)</option>
<option value="om" data-otp-enabled="false" >Oman (+968)</option>
<option value="pk" data-otp-enabled="false" >Pakistan (+92)</option>
<option value="ps" data-otp-enabled="false" >Palestinian Territory (+970)</option>
<option value="pa" data-otp-enabled="false" >Panama (+507)</option>
<option value="py" data-otp-enabled="false" >Paraguay (+595)</option>
<option value="pe" data-otp-enabled="false" >Peru (+51)</option>
<option value="ph" data-otp-enabled="false" >Philippines (+63)</option>
<option value="pl" data-otp-enabled="false" >Poland (+48)</option>
<option value="pt" data-otp-enabled="false" >Portugal (+351)</option>
<option value="pr" data-otp-enabled="false" >Puerto Rico (+1)</option>
<option value="qa" data-otp-enabled="false" >Qatar (+974)</option>
<option value="re" data-otp-enabled="false" >Reunion/Mayotte (+262)</option>
<option value="ro" data-otp-enabled="false" >Romania (+40)</option>
<option value="ru" data-otp-enabled="false" >Russia/Kazakhstan (+7)</option>
<option value="rw" data-otp-enabled="false" >Rwanda (+250)</option>
<option value="ws" data-otp-enabled="false" >Samoa (+685)</option>
<option value="sm" data-otp-enabled="false" >San Marino (+378)</option>
<option value="sa" data-otp-enabled="false" >Saudi Arabia (+966)</option>
<option value="sn" data-otp-enabled="false" >Senegal (+221)</option>
<option value="rs" data-otp-enabled="false" >Serbia (+381)</option>
<option value="sc" data-otp-enabled="false" >Seychelles (+248)</option>
<option value="sl" data-otp-enabled="false" >Sierra Leone (+232)</option>
<option value="sg" data-otp-enabled="false" >Singapore (+65)</option>
<option value="sk" data-otp-enabled="false" >Slovakia (+421)</option>
<option value="si" data-otp-enabled="false" >Slovenia (+386)</option>
<option value="za" data-otp-enabled="false" >South Africa (+27)</option>
<option value="es" data-otp-enabled="false" >Spain (+34)</option>
<option value="lk" data-otp-enabled="false" >Sri Lanka (+94)</option>
<option value="kn" data-otp-enabled="false" >St Kitts and Nevis (+1)</option>
<option value="lc" data-otp-enabled="false" >St Lucia (+1)</option>
<option value="vc" data-otp-enabled="false" >St Vincent Grenadines (+1)</option>
<option value="sd" data-otp-enabled="false" >Sudan (+249)</option>
<option value="sr" data-otp-enabled="false" >Suriname (+597)</option>
<option value="sz" data-otp-enabled="false" >Swaziland (+268)</option>
<option value="se" data-otp-enabled="false" >Sweden (+46)</option>
<option value="ch" data-otp-enabled="false" >Switzerland (+41)</option>
<option value="tw" data-otp-enabled="false" >Taiwan (+886)</option>
<option value="tj" data-otp-enabled="false" >Tajikistan (+992)</option>
<option value="tz" data-otp-enabled="false" >Tanzania (+255)</option>
<option value="th" data-otp-enabled="false" >Thailand (+66)</option>
<option value="tg" data-otp-enabled="false" >Togo (+228)</option>
<option value="to" data-otp-enabled="false" >Tonga (+676)</option>
<option value="tt" data-otp-enabled="false" >Trinidad and Tobago (+1)</option>
<option value="tn" data-otp-enabled="false" >Tunisia (+216)</option>
<option value="tr" data-otp-enabled="false" >Turkey (+90)</option>
<option value="tc" data-otp-enabled="false" >Turks and Caicos Islands (+1)</option>
<option value="ug" data-otp-enabled="false" >Uganda (+256)</option>
<option value="ua" data-otp-enabled="false" >Ukraine (+380)</option>
<option value="ae" data-otp-enabled="false" >United Arab Emirates (+971)</option>
<option value="gb" data-otp-enabled="false" >United Kingdom (+44)</option>
<option value="us" data-otp-enabled="false" >United States (+1)</option>
<option value="uy" data-otp-enabled="false" >Uruguay (+598)</option>
<option value="uz" data-otp-enabled="false" >Uzbekistan (+998)</option>
<option value="ve" data-otp-enabled="false" >Venezuela (+58)</option>
<option value="vn" data-otp-enabled="false" >Vietnam (+84)</option>
<option value="vg" data-otp-enabled="false" >Virgin Islands, British (+1)</option>
<option value="vi" data-otp-enabled="false" >Virgin Islands, U.S. (+1)</option>
<option value="ye" data-otp-enabled="false" >Yemen (+967)</option>
<option value="zm" data-otp-enabled="false" >Zambia (+260)</option>
<option value="zw" data-otp-enabled="false" >Zimbabwe (+263)</option></select>
</div>
</div>
</div>
<label class="sub-label" for="phone-number-m8f0dnxtmjbz">Enter mobile number</label>
<div class="controls phone-number" data-js-hook="modal-open-incident-subscribe-phone-number">
<div class="flex-container">
<input type="text" name="phone_number" id="phone-number-m8f0dnxtmjbz" data-js-hook="phone-number" />
<input type="hidden" name="incident-code-m8f0dnxtmjbz" id="incident-code-m8f0dnxtmjbz" value="m8f0dnxtmjbz" autocomplete="off" />
<a class="btn-change-number-incident" id="btn-change-number-incident-m8f0dnxtmjbz" style="display: none;" data-incident-code="m8f0dnxtmjbz" href="#">
Edit number
</a> <a class="btn-subcriber-send-otp" id="btn-subcriber-send-otp-m8f0dnxtmjbz" style="display: none;" data-incident-code="m8f0dnxtmjbz" href="#">
Send OTP
</a> </div>
</div>
<div class="sms-atl-error" id='sms-atl-error-m8f0dnxtmjbz'></div>
<div class="opt-container-section" id='otp-container-incident-m8f0dnxtmjbz' style="display:none">
<label class="sub-label" for="otp">Enter the OTP sent</label>
<div class="flex-container">
<input name="otp" id='otp-field-m8f0dnxtmjbz' type="text" class="prepend" disabled>
<a class="resend-otp" id="resend-otp-m8f0dnxtmjbz" style="display: none;" data-incident-code="m8f0dnxtmjbz" href="#">
Resend OTP
</a> <span class="timer-incident" id='timer-incident-m8f0dnxtmjbz' style="display:none">&nbsp;in <span id='countdown-incident-m8f0dnxtmjbz'>30</span> seconds</span>
</div>
<div class="info-row flex-container">
<div class="info-icon"><svg width="2vh" height="2vh" viewBox="0 0 21 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="status-embed-svg-info-icon">
<defs>
<path d="M2,12 C2,6.47666667 6.47666667,2 12,2 C17.5233333,2 22,6.47666667 22,12 C22,17.5233333 17.5233333,22 12,22 C6.47666667,22 2,17.5233333 2,12 Z M4,12 C4,16.4187638 7.58123617,20 12,20 C16.4187638,20 20,16.4187638 20,12 C20,7.58123617 16.4187638,4 12,4 C7.58123617,4 4,7.58123617 4,12 Z M11,11.0029293 C11,10.4490268 11.4438648,10 12,10 C12.5522847,10 13,10.4378814 13,11.0029293 L13,15.9970707 C13,16.5509732 12.5561352,17 12,17 C11.4477153,17 11,16.5621186 11,15.9970707 L11,11.0029293 Z M12,9 C11.4477153,9 11,8.55228475 11,8 C11,7.44771525 11.4477153,7 12,7 C12.5522847,7 13,7.44771525 13,8 C13,8.55228475 12.5522847,9 12,9 Z" id="path-info"></path>
</defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-702.000000, -945.000000)">
<g id="global/info" transform="translate(700.500000, 943.500000)">
<mask id="mask-info" fill="white">
<use xlink:href="#path-info"></use>
</mask>
<use id="Combined-Shape" fill="#42526E" fill-rule="nonzero" xlink:href="#path-info"></use>
<g id="Neutral-/-N000" mask="url(#mask-info)" fill-rule="evenodd">
<polygon points="0 24 24 24 24 0 0 0"></polygon>
</g>
</g>
</g>
</g>
</svg>
</div>
<div>To receive SMS updates, please verify your number. To proceed with just email click ‘Subscribe’ </div>
</div>
</div>
</div>
</div>
<div class="modal-footer incident-subscribe">
<!-- tests fail if static width isn't present ¯\_(ツ)_/¯ -->
<button name="button" type="submit" class="flat-button cpt-button incident-subscribe-btn-captcha" id="subscribe-btn-m8f0dnxtmjbz" onclick="submitCaptchaIncidentSubscribe(event)">Subscribe to Incident</button>
<input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" />
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response" value="false" autocomplete="off" />
<div class="terms_and_privacy_information left small">Message and data rates may apply. By subscribing you agree to our <a target="_blank" rel="noopener" class="accessible-link" href="https://buildkite.com/privacy-policy">Privacy Policy</a>, the Atlassian <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/product-specific-terms#statuspage-specific-terms">Terms of Service</a>, and the Atlassian <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/privacy-policy">Privacy Policy</a>. 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>
</div>
</form> </div>
<script>
$(function () {
const phoneNumberInputIncident = $('#phone-number-m8f0dnxtmjbz');
const phoneCountrySelect = $('#phone-country-m8f0dnxtmjbz');
const errorDiv = $('#sms-atl-error-m8f0dnxtmjbz');
const phoneCountryDiv = $('#phone-number-code-m8f0dnxtmjbz');
if(errorDiv.length){
function checkSelectedCountry() {
const selectedCountry = phoneCountrySelect.val();
const isOtpEnabled = phoneCountryDiv.attr('data-otp-enabled') === 'true';
if(false && selectedCountry === 'sg') { // Replace 'SG' with the actual value representing Singapore in your select tag
phoneNumberInputIncident.prop('disabled', true);
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.`);
} else {
phoneNumberInputIncident.prop('readOnly', false);
errorDiv.html('');
if(false){
$('#btn-change-number-incident-m8f0dnxtmjbz').css('display', 'none');
$('#resend-otp-m8f0dnxtmjbz').css('display', 'none');
$('#timer-incident-m8f0dnxtmjbz').css('display', 'none');
if(isOtpEnabled){
$('#otp-container-incident-m8f0dnxtmjbz').css('display', 'block');
$('#btn-subcriber-send-otp-m8f0dnxtmjbz').css('display', 'block');
}
else {
$('#otp-container-incident-m8f0dnxtmjbz').css('display', 'none');
$('#btn-subcriber-send-otp-m8f0dnxtmjbz').css('display', 'none');
}
}
}
}
phoneCountrySelect.on('change', checkSelectedCountry);
checkSelectedCountry();
}
});
document.addEventListener('DOMContentLoaded', function() {
const dropdowns = document.querySelectorAll('.phone-country-dropdown');
if (dropdowns.length > 0) {
dropdowns.forEach(function(dropdown) {
const dropdownId = dropdown.id;
const incidentCode = dropdownId.split('-').pop();
const wrapperDiv = $('#phone-number-code-' + incidentCode);
function updateOtpEnabledAttribute() {
const selectedOption = dropdown.options[dropdown.selectedIndex];
const otpEnabled = selectedOption.getAttribute('data-otp-enabled');
wrapperDiv.attr('data-otp-enabled', otpEnabled);
}
dropdown.addEventListener('change', updateOtpEnabledAttribute);
updateOtpEnabledAttribute();
});
}
});
var countdownTimers = {};
var phoneNumberInputIncident = $('#phone-number-m8f0dnxtmjbz');
var RESEND_TIMER = 30;
$(function() {
$('#subscribe-form-m8f0dnxtmjbz').on('ajax:success', function(e, data, status, xhr){
var $form = $(this);
var formId = $form.attr('id');
var incidentCode = formId.split('-').pop();
$('#btn-change-number-incident-' + incidentCode).css('display', 'block');
if ( $('#btn-change-number-incident-'+ incidentCode).css('display') !== 'none') {
$('#btn-change-number-incident-'+ incidentCode).css('display', 'none');
$('#btn-subcriber-send-otp-'+ incidentCode).css('display', 'block');
$('#otp-container-incident-'+ incidentCode).css('display', 'block');
$('#resend-otp-'+ incidentCode).css('display', 'none');
$('#timer-incident-'+ incidentCode).css('display', 'none');
$('#phone-number-' + incidentCode).prop('readOnly', false);
$('#otp-field-' + incidentCode).val('').prop('disabled', true);
}
if(countdownTimers){
clearInterval(countdownTimers[incidentCode]);
}
});
$('#btn-change-number-incident-m8f0dnxtmjbz').on('click', function (e) {
var incidentCode = $(this).data('incident-code');
showSendOTP(incidentCode);
return false;
});
$('#btn-subcriber-send-otp-m8f0dnxtmjbz').on('click', function (e) {
let incidentCode = $(this).data('incident-code');
let phoneNumber = $('#phone-number-' + incidentCode).val();
let countryCode = $('#phone-country-' + incidentCode).val();
let incidentCodeField = $('#incident-code-' + incidentCode).val();
sendOtpRequest(phoneNumber, countryCode, incidentCodeField, function (data, status) {
var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {};
HRB.utils.notify(data.text, messageOptions);
e.preventDefault();
if (data.type === 'success') {
showChangeNumber(incidentCode);
}
});
});
$('#resend-otp-m8f0dnxtmjbz').on('click', function(e) {
let incidentCode = $(this).data('incident-code');
let phoneNumber = $('#phone-number-' + incidentCode).val();
let countryCode = $('#phone-country-' + incidentCode).val();
let incidentCodeField = $('#incident-code-' + incidentCode).val();
sendOtpRequest(phoneNumber, countryCode, incidentCodeField, function (data, status) {
var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {};
HRB.utils.notify(data.text, messageOptions);
e.preventDefault();
disableResendIncident(incidentCode);
if (data.type === 'success') {
var display = $('#countdown-incident-' + incidentCode);
startTimerIncident(RESEND_TIMER, display, incidentCode );
}
});
});
})
function sendOtpRequest(phoneNumber, countryCode, incidentCode, onSuccess) {
$.ajax({
type: 'POST',
url: "/subscriptions/new-sms",
data: {
phone_number: phoneNumber,
phone_country: countryCode,
incident_code: incidentCode,
type: 'resend'
},
}).done(onSuccess);
}
function showChangeNumber(incidentCode) {
$('#btn-change-number-incident-' + incidentCode).css('display', 'block');
$('#btn-subcriber-send-otp-' + incidentCode).css('display', 'none');
$('#otp-field-' + incidentCode).val('').prop('disabled', false);
$('#phone-number-' + incidentCode).prop('readOnly', true);
$('#resend-otp-'+ incidentCode).css('display', 'block');
var display = $('#countdown-incident-' + incidentCode);
startTimerIncident(RESEND_TIMER, display, incidentCode)
}
function showSendOTP(incidentCode) {
$('#btn-change-number-incident-' + incidentCode).css('display', 'none');
$('#btn-subcriber-send-otp-' + incidentCode).css('display', 'block');
$('#otp-field-' + incidentCode).val('').prop('disabled', true);
$('#phone-number-' + incidentCode).prop('readOnly', false);
$('#resend-otp-'+ incidentCode).css('display', 'none');
$('#timer-incident-'+ incidentCode).css('display', 'none');
clearInterval(countdownTimers[incidentCode]);
}
function startTimerIncident(duration, display, incidentCode){
var timerIncident = duration, seconds;
clearInterval(countdownTimers[incidentCode]);
countdownTimers[incidentCode] = setInterval(function () {
seconds = parseInt(timerIncident % 60, 10);
display.text(seconds);
$('#timer-incident-'+ incidentCode).css('display', 'block');
if(--timerIncident < 0){
enableResendIncident(incidentCode);
clearInterval(countdownTimers[incidentCode]);
}
}, 1000);
disableResendIncident(incidentCode);
}
function enableResendIncident(incidentCode){
$('#resend-otp-' + incidentCode).css('color', '');
$('#resend-otp-' + incidentCode).css('pointer-events', '');
$('#timer-incident-'+ incidentCode).css('display', 'none');
}
function disableResendIncident(incidentCode){
$('#resend-otp-' + incidentCode).css('color', 'grey');
$('#resend-otp-' + incidentCode).css('pointer-events', 'none');
}
</script>
<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_manifest-9446cbd3af4b0e3706e85200ffeb5f09d6410458c7aea582354bfd4bc5546b5e.js"></script>
<div id="cpt-notification-container" role="status" aria-live="polite" aria-atomic="true"></div>
<!-- all of the content_for stuff -->
<script src="https://dka575ofm4ao0.cloudfront.net/assets/register_subscription_form-589b657fec607087fc5c740c568270907310bc4f6aaa20256e70f01b103025ca.js"></script>
<script type="text/javascript">
$(function() {
SP.currentPage.registerSubscriptionForm('email');
SP.currentPage.registerSubscriptionForm('sms');
SP.currentPage.registerSubscriptionForm('webhook');
});
$(function() {
SP.currentPage.registerSubscriptionForm('m8f0dnxtmjbz');
});
</script>
<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_common-a86dffb81955091741c3de8bded6ce66ae0c6d8f736b57b580f853d9f892727e.js"></script>
<script>
$(function() { // docks custom footer
var content = $('.layout-content > .container')
, header = $('.custom-header-container')
, footer = $('.custom-footer-container')
if (!footer.length) {
content.addClass('default-spacing');
}
else {
var screenHeight = $(window).outerHeight()
, containerHeight = $('.layout-content > .container').outerHeight(true) || null
, headerHeight = $('.custom-header-container').outerHeight(true) || null
, footerHeight = $('.custom-footer-container').outerHeight(true) || null;
if (screenHeight > containerHeight + footerHeight + headerHeight) {
$('.layout-content > .container').css('padding-bottom', screenHeight - containerHeight - footerHeight - headerHeight);
}
}
});
$(function() {
$(document).on('ajax:complete', '.modal.in', function(e) {
// Close the active modal.
$('.modal.in').modal('hide');
});
});
$(function() {
var timeDifference = function(previous) {
var msPerMinute = 60 * 1000;
var msPerHour = msPerMinute * 60;
var msPerDay = msPerHour * 24;
var msPerMonth = msPerDay * 30;
var msPerYear = msPerDay * 365;
var now = Date.now();
var elapsedMs = now - previous;
var elapsed = Math.round(elapsedMs/msPerMinute);
if (elapsed === 0) {
return elapsedString(1) + ' minute ago. ';
}
else if (elapsed < 60) {
return elapsedString(elapsed) + ' minute' + plural(elapsed) + ' ago. ';
}
elapsed = Math.round(elapsedMs/msPerHour);
if (elapsed < 24) {
return elapsedString(elapsed) + ' hour' + plural(elapsed) + ' ago. ';
}
elapsed = Math.round(elapsedMs/msPerDay);
if (elapsed < 31) {
return elapsedString(elapsed) + ' day' + plural(elapsed) + ' ago. ';
}
elapsed = Math.round(elapsedMs/msPerMonth);
if (elapsed < 12) {
return elapsedString(elapsed) + ' month' + plural(elapsed) + ' ago. ';
}
elapsed = Math.round(elapsedMs/msPerYear);
return elapsedString(elapsed) + ' year' + plural(elapsed) + ' ago. ';
};
var elapsedString = function(elapsed) {
return '<var data-var="num">' + elapsed + '</var>'
};
var plural = function(x) {
return (x <= 1) ? '' : 's';
};
var relative_dates = $('span.ago');
relative_dates.each(function() {
var $el = $(this);
var time = $el.data("datetime-unix");
$el.html(timeDifference(time));
})
});
</script>
<script>
/** INITIALIZATION **/
var recaptchaIds = {}
// Unfortunately there's no unique selectors on the parent divs that recaptcha adds. The first unique selector
// is the iframe rendered 2 levels deep. So this waits until the iframes are added to the page, then finds
// the parent div and sets the z index so that it'll render above our modals & dropdowns from the start.
function setZIndex(captchaCount, startTime) {
// bail after 10s just in case so we don't do this forever if something whaky happens
if (new Date() - startTime > 10000) {
return;
}
var iframes = document.querySelectorAll('iframe[title="recaptcha challenge"]');
if (iframes.length != captchaCount) {
setTimeout(function() {
setZIndex(captchaCount, startTime);
}, 500);
}
for (var i = 0; i < iframes.length; i++) {
// incident subscribe modal is 1050, so this has to be above that
iframes[i].parentElement.parentElement.style.zIndex = "1100";
}
}
function updateCaptchaIframeTitle(captchaCount, startTime, updates=0) {
if (new Date() - startTime > 10000 || captchaCount === updates) {
return;
}
var iframesWithTitle = document.querySelectorAll('iframe[title="recaptcha challenge expires in two minutes"]');
if (iframesWithTitle.length != captchaCount) {
setTimeout(function() {
updateCaptchaIframeTitle(captchaCount, startTime, iframesWithTitle.length + updates);
}, 500);
}
for (var i = 0; i < iframesWithTitle.length; i++) {
iframesWithTitle[i].title = "recaptcha";
}
}
function addIncidentCaptcha() {
var incidentCaptcha = document.createElement('div');
incidentCaptcha.setAttribute('id', 'subscribe-incident-recaptcha');
incidentCaptcha.setAttribute('class', 'g-recaptcha');
incidentCaptcha.setAttribute('data-sitekey', '6LcZ-b0UAAAAAENi956aWzynTT2ZJ80dGU3F80Op');
incidentCaptcha.setAttribute('data-callback', 'submitIncidentSubscriberSuccess');
incidentCaptcha.setAttribute('data-error-callback', 'submitIncidentSubscriberError');
incidentCaptcha.setAttribute('data-size', 'invisible');
document.body.appendChild(incidentCaptcha);
var incidentCode = document.createElement('input');
incidentCode.setAttribute('type', 'hidden');
incidentCode.setAttribute('id', 'submit_incident_code');
document.body.appendChild(incidentCode);
}
var onloadCallback = function() {
// if there is an incident, then add incident captcha element
if (document.getElementsByClassName('modal-open-incident-subscribe').length > 0) {
addIncidentCaptcha();
}
var captchas = document.getElementsByClassName("g-recaptcha");
for(var i = 0; i < captchas.length; i++) {
var elId = captchas[i].id;
recaptchaIds[elId] = grecaptcha.enterprise.render(elId);
}
setZIndex(captchas.length, new Date());
updateCaptchaIframeTitle(captchas.length, new Date());
}
/** SUBSCRIBE DROPDOWN */
// callbacks for captcha success
function submitNewSubscriber(type, error) {
if (error) document.querySelector('#subscribe-form-' + type + ' #captcha_error').value = 'true';
document.getElementById('subscribe-form-' + type).dispatchEvent(new Event('submit', {bubbles: true, cancelable: true}));
grecaptcha.enterprise.reset(recaptchaIds['subscribe-btn-' + type]);
}
function submitNewEmailSubscriber(token) {
submitNewSubscriber('email');
}
function submitNewSmsSubscriber(token) {
submitNewSubscriber('sms');
}
function submitNewWebhookSubscriber(token) {
submitNewSubscriber('webhook');
}
function submitIncidentSubscriber(token, error) {
var incidentCode = document.getElementById('submit_incident_code').value;
var incidentForm = document.getElementById('subscribe-form-' + incidentCode);
incidentForm.querySelector('input[name="captcha_error"]').value = error;
incidentForm.querySelector('input[name="g-recaptcha-response"]').value = token;
incidentForm.dispatchEvent(new Event('submit', {bubbles: true, cancelable: true}));
grecaptcha.enterprise.reset(recaptchaIds['subscribe-incident-recaptcha']);
}
function submitIncidentSubscriberSuccess(token) {
submitIncidentSubscriber(token, 'false');
}
// callbacks if we get captcha network errors
function emailSubscriberCaptchaError(token) {
submitNewSubscriber('email', true);
}
function smsSubscriberCaptchaError(token) {
submitNewSubscriber('sms', true);
}
function webhookSubscriberCaptchaError(token) {
submitNewSubscriber('webhook', true);
}
function submitIncidentSubscriberError(token) {
submitIncidentSubscriber(token, 'true');
}
// tracking clicks
['email', 'sms', 'webhook'].forEach(function(type) {
var el = document.getElementById('subscribe-btn-' + type);
el && el.addEventListener("click", function() {
$.ajax({
type: "POST",
url: "/subscriptions/track_attempt",
data: {
type: type
}
})
})
})
// form submission success callbacks
$('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){
if (data.type === 'success') {
SP.currentPage.updatesDropdown.hide();
var emailField = document.getElementById('email');
if (emailField) {
emailField.value = '';
}
}
});
$('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){
if (data.type === 'success' && data.otp_flow !== true) {
SP.currentPage.updatesDropdown.hide();
var phoneField = document.getElementById('phone-number');
if (phoneField) {
phoneField.value = '';
}
}
});
$('#subscribe-form-webhook').on('ajax:success', function(e, data, status, xhr){
if (data.type === 'success') {
SP.currentPage.updatesDropdown.hide();
document.getElementById('endpoint-webhooks').value = '';
document.getElementById('email-webhooks').value = '';
}
});
$('a.subscribe').on('click', function() {
document.body.style.overflow = "hidden";
document.body.style.height = "100vh";
});
$('div.modal-open-incident-subscribe').on('hidden', function(){
document.body.style.overflow = "";
document.body.style.height = "";
});
function submitCaptchaIncidentSubscribe(event) {
var incidentCode = event.target.id.split('-')[2];
event.preventDefault();
$.ajax({
type: "POST",
url: "/subscriptions/track_attempt",
data: {
type: 'incident'
}
})
document.getElementById('submit_incident_code').value = incidentCode;
grecaptcha.enterprise.execute(recaptchaIds['subscribe-incident-recaptcha']);
}
</script>
<script src='https://www.recaptcha.net/recaptcha/enterprise.js?onload=onloadCallback&render=explicit' async defer></script>
<script src="https://dka575ofm4ao0.cloudfront.net/packs/common-3e6e8c878eea26f45b29.chunk.js"></script>
<script src="https://dka575ofm4ao0.cloudfront.net/packs/globals-f12471d5e878ec0f0705.chunk.js"></script>
<script src="https://dka575ofm4ao0.cloudfront.net/packs/runtime-33399279767e29d9b814.js"></script>
<script>
window.addEventListener('load', function () {
const urlParams = new URLSearchParams(window.location.search);
const messageToken = urlParams.get('slack_message_token');
const channelName = escape(urlParams.get('channel_name'));
if(!!messageToken) {
switch(messageToken) {
case 'slack_auth_error':
HRB.utils.notify('The Slack authorization attempt was unsuccessful. Try again.', {cssClass:'error'});
break;
case 'subscribers_disabled_error':
HRB.utils.notify('Slack subscriptions are not enabled on this page.', {cssClass:'error'});
break;
case 'direct_message_channel_error':
HRB.utils.notify('Subscriptions aren’t supported in direct messages. Try subscribing again and choose a channel instead.', {cssClass:'error'});
break
case 'duplicate_error':
HRB.utils.notify("You're already subscribed to get Slack notifications in that channel.", {cssClass:'error'});
break;
case 'duplicate_private_channel_error':
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'});
break;
case 'default_success':
HRB.utils.notify("You're now subscribed to get Statuspage updates in Slack!", {cssClass:'success'});
break;
case 'private_channel_success':
HRB.utils.notify(`IMPORTANT: Invite the @Statuspage app to your Slack channel #${channelName} to start getting status updates.`, {cssClass:'success'});
break;
}
}
});
</script>
<!-- FOR FLASH NOTICES -->
<!-- FOR ERROR -->
<script>
$(function() {
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.buildkitestatus.com&amp;utm_content=SP-notifications&amp;utm_medium=powered-by&amp;utm_source=inapp">Powered by Atlassian Statuspage</a></span>');
var setPoweredByStyles = function() {
if (!$('.powered-by').length) {
$link.appendTo($('.page-footer'))
}
$('.powered-by').attr('style', 'display: inline !important; visibility:visible !important; opacity: 1 !important; position:static !important; text-indent:0px !important; transform:scale(1) !important');
}
setInterval(setPoweredByStyles, 1000);
});
</script>
</body>
</html>