Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/elements/framework/mr-issue-slo/slo-rules.js b/static_src/elements/framework/mr-issue-slo/slo-rules.js
new file mode 100644
index 0000000..e351ae0
--- /dev/null
+++ b/static_src/elements/framework/mr-issue-slo/slo-rules.js
@@ -0,0 +1,195 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Determining Issues' statuses relative to SLO rules.
+ *
+ * See go/monorail-slo-v0 for more info.
+ */
+
+/**
+ * A rule determining the compliance of an issue with regard to an SLO.
+ * @typedef {Object} SloRule
+ * @property {function(Issue): SloStatus} statusFunction
+ */
+
+/**
+ * Potential statuses of an issue relative to an SLO's completion criteria.
+ * @enum {string}
+ */
+export const SloCompletionStatus = {
+ /** The completion criteria for the SloRule have not been satisfied. */
+ INCOMPLETE: 'INCOMPLETE',
+ /** The completion criteria for the SloRule have been satisfied. */
+ COMPLETE: 'COMPLETE',
+};
+
+/**
+ * The status of an issue with regard to an SloRule.
+ * @typedef {Object} SloStatus
+ * @property {SloRule} rule The rule that generated this status.
+ * @property {Date} target The time the Issue must move to completion, or null
+ * if the issue has already moved to completion.
+ * @property {SloCompletionStatus} completion Issue's completion status.
+ */
+
+/**
+ * Chrome OS Software's SLO for issue closure (go/chromeos-software-bug-slos).
+ *
+ * Implementation based on the queries defined in Sheriffbot
+ * https://chrome-internal.googlesource.com/infra/infra_internal/+/refs/heads/main/appengine/sheriffbot/src/sheriffbot/bug_slo_daily_queries.py
+ *
+ * @const {SloRule}
+ * @private Only visible for testing.
+ */
+export const _CROS_CLOSURE_SLO = {
+ statusFunction: (issue) => {
+ if (!_isCrosClosureEligible(issue)) {
+ return null;
+ }
+
+ const pri = getPriFromIssue(issue);
+ const daysToClose = _CROS_CLOSURE_SLO_DAYS_BY_PRIORITY[pri];
+
+ if (!daysToClose) {
+ // No applicable SLO found issues with this priority.
+ return null;
+ }
+ // Return a complete status for closed issues.
+ if (issue.statusRef && !issue.statusRef.meansOpen) {
+ return {
+ rule: _CROS_CLOSURE_SLO,
+ target: null,
+ completion: SloCompletionStatus.COMPLETE};
+ }
+
+ // Set the target based on the opening and the daysToClose.
+ const target = new Date(issue.openedTimestamp * 1000);
+ target.setDate(target.getDate() + daysToClose);
+ return {
+ rule: _CROS_CLOSURE_SLO,
+ target: target,
+ completion: SloCompletionStatus.INCOMPLETE};
+ },
+};
+
+/**
+ * @param {Issue} issue
+ * @return {string?} the pri's value, if found.
+ */
+const getPriFromIssue = (issue) => {
+ for (const fv of issue.fieldValues) {
+ if (fv.fieldRef.fieldName === 'Pri') {
+ return fv.value;
+ }
+ }
+};
+
+/**
+ * The number of days (since the issue was opened) allowed for it to be fixed.
+ * @private Only visible for testing.
+ */
+export const _CROS_CLOSURE_SLO_DAYS_BY_PRIORITY = Object.freeze({
+ '1': 42,
+});
+
+// https://chrome-internal.googlesource.com/infra/infra_internal/+/refs/heads/main/appengine/sheriffbot/src/sheriffbot/bug_slo_daily_queries.py#97
+const CROS_ELIGIBLE_COMPONENT_PATHS = new Set([
+ 'OS>Systems>CrashReporting',
+ 'OS>Systems>Displays',
+ 'OS>Systems>Feedback',
+ 'OS>Systems>HaTS',
+ 'OS>Systems>Input',
+ 'OS>Systems>Input>Keyboard',
+ 'OS>Systems>Input>Mouse',
+ 'OS>Systems>Input>Shortcuts',
+ 'OS>Systems>Input>Touch',
+ 'OS>Systems>Metrics',
+ 'OS>Systems>Multidevice',
+ 'OS>Systems>Multidevice>Messages',
+ 'OS>Systems>Multidevice>SmartLock',
+ 'OS>Systems>Multidevice>Tethering',
+ 'OS>Systems>Network>Bluetooth',
+ 'OS>Systems>Network>Cellular',
+ 'OS>Systems>Network>VPN',
+ 'OS>Systems>Network>WiFi',
+ 'OS>Systems>Printing',
+ 'OS>Systems>Settings',
+ 'OS>Systems>Spellcheck',
+ 'OS>Systems>Update',
+ 'OS>Systems>Wallpaper',
+ 'OS>Systems>WirelessCharging',
+ 'Platform>Apps>Feedback',
+ 'UI>Shell>Networking',
+]);
+
+/**
+ * Determines if an issue is eligible for _CROS_CLOSURE_SLO.
+ * @param {Issue} issue
+ * @return {boolean}
+ * @private Only visible for testing.
+ */
+export const _isCrosClosureEligible = (issue) => {
+ // If at least one component applies, continue.
+ const hasEligibleComponent = issue.componentRefs.some(
+ (component) => CROS_ELIGIBLE_COMPONENT_PATHS.has(component.path));
+ if (!hasEligibleComponent) {
+ return false;
+ }
+
+ let priority = null;
+ let hasMilestone = false;
+ for (const fv of issue.fieldValues) {
+ if (fv.fieldRef.fieldName === 'Type') {
+ // These types don't apply.
+ if (fv.value === 'Feature' || fv.value === 'FLT-Launch' ||
+ fv.value === 'Postmortem-Followup' || fv.value === 'Design-Review') {
+ return false;
+ }
+ }
+ if (fv.fieldRef.fieldName === 'Pri') {
+ priority = fv.value;
+ }
+ if (fv.fieldRef.fieldName === 'M') {
+ hasMilestone = true;
+ }
+ }
+ // P1 issues with milestones don't apply.
+ if (priority === '1' && hasMilestone) {
+ return false;
+ }
+ // Issues with the ChromeOS_No_SLO label don't apply.
+ for (const labelRef of issue.labelRefs) {
+ if (labelRef.label === 'ChromeOS_No_SLO') {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+ * Active SLO Rules.
+ * @const {Array<SloRule>}
+ */
+const SLO_RULES = [_CROS_CLOSURE_SLO];
+
+/**
+ * Determines the SloStatus for the given issue.
+ * @param {Issue} issue The issue to check.
+ * @return {SloStatus} The status of the issue, or null if no rules apply.
+ */
+export const determineSloStatus = (issue) => {
+ try {
+ for (const rule of SLO_RULES) {
+ const status = rule.statusFunction(issue);
+ if (status) {
+ return status;
+ }
+ }
+ } catch (error) {
+ // Don't bubble up any errors in SLO_RULES functions, which might sometimes
+ // be written/updated by client teams.
+ }
+ return null;
+};