Merge "Support to validate the code owner config files in a revision/patch set"
diff --git a/ui/code-owners-service.js b/ui/code-owners-service.js
index 426d0a7..86dc89c 100644
--- a/ui/code-owners-service.js
+++ b/ui/code-owners-service.js
@@ -37,6 +37,19 @@
};
/**
+ * @enum
+ */
+const UserRole = {
+ ANONYMOUS: 'ANONYMOUS',
+ AUTHOR: 'AUTHOR',
+ CHANGE_OWNER: 'CHANGE_OWNER',
+ REVIEWER: 'REVIEWER',
+ CC: 'CC',
+ REMOVED_REVIEWER: 'REMOVED_REVIEWER',
+ OTHER: 'OTHER',
+}
+
+/**
* Responsible for communicating with the rest-api
*
* @see resources/Documentation/rest-api.md
@@ -123,6 +136,12 @@
* Initial fetches.
*/
init() {
+ this.accountPromise = this.restApi.getLoggedIn().then(loggedIn => {
+ if (!loggedIn) {
+ return undefined;
+ }
+ return this.restApi.getAccount();
+ });
this.statusPromise = this.codeOwnerApi
.listOwnerStatus(this.change._number)
.then(res => {
@@ -134,6 +153,57 @@
rawStatuses: res.file_code_owner_statuses,
};
});
+
+ }
+
+ /**
+ * Returns the role of the current user. The returned value reflects the
+ * role of the user at the time when the change is loaded.
+ * For example, if a user removes themselves as a reviewer, the returned
+ * role 'REVIEWER' remains unchanged until the change view is reloaded.
+ */
+ getLoggedInUserInitialRole() {
+ return this.accountPromise.then((account) => {
+ if (!account) {
+ return UserRole.ANONYMOUS;
+ }
+ const change = this.change;
+ if (
+ change.revisions &&
+ change.current_revision &&
+ change.revisions[change.current_revision]
+ ) {
+ const commit = change.revisions[change.current_revision].commit;
+ if (
+ commit &&
+ commit.author &&
+ account.email &&
+ commit.author.email === account.email
+ ) {
+ return UserRole.AUTHOR;
+ }
+ }
+ if(change.owner._account_id === account._account_id) {
+ return UserRole.CHANGE_OWNER;
+ }
+ if(change.reviewers) {
+ if(this._accountInReviewers(change.reviewers.REVIEWER, account)) {
+ return UserRole.REVIEWER;
+ } else if (this._accountInReviewers(change.reviewers.CC, account)) {
+ return UserRole.CC;
+ } else if (this._accountInReviewers(change.reviewers.REMOVED, account)) {
+ return UserRole.REMOVED_REVIEWER;
+ }
+ }
+ return UserRole.OTHER;
+ })
+ }
+
+ _accountInReviewers(reviewers, account) {
+ if(!reviewers) {
+ return false;
+ }
+ return reviewers.some(reviewer => reviewer._account_id === account._account_id);
}
getStatus() {
@@ -414,4 +484,4 @@
}
return this.ownerService;
}
-}
\ No newline at end of file
+}
diff --git a/ui/owner-requirement.js b/ui/owner-requirement.js
index e456976..610fdd4 100644
--- a/ui/owner-requirement.js
+++ b/ui/owner-requirement.js
@@ -123,13 +123,14 @@
return this.ownerService.getStatus()
.then(({rawStatuses}) => {
this._statusCount = this._getStatusCount(rawStatuses);
-
- // Send a metric with overall summary when code owners submit
- // requirement shown and finished fetching status
- this.reporting.reportLifeCycle(
- 'owners-submit-requirement-summary-shown',
- {...this._statusCount}
- );
+ this.ownerService.getLoggedInUserInitialRole().then(role => {
+ // Send a metric with overall summary when code owners submit
+ // requirement shown and finished fetching status
+ this.reporting.reportLifeCycle(
+ 'owners-submit-requirement-summary-shown',
+ {...this._statusCount, user_role: role}
+ );
+ });
})
.finally(() => {
this._isLoading = false;
@@ -205,9 +206,11 @@
})
);
ownerState.expandSuggestion = true;
-
- this.reporting.reportInteraction('suggest-owners-from-submit-requirement');
+ this.ownerService.getLoggedInUserInitialRole().then(role => {
+ this.reporting.reportInteraction(
+ 'suggest-owners-from-submit-requirement', {user_role: role});
+ });
}
}
-customElements.define(OwnerRequirementValue.is, OwnerRequirementValue);
\ No newline at end of file
+customElements.define(OwnerRequirementValue.is, OwnerRequirementValue);
diff --git a/ui/suggest-owners-trigger.js b/ui/suggest-owners-trigger.js
index 5745545..09fd6f8 100644
--- a/ui/suggest-owners-trigger.js
+++ b/ui/suggest-owners-trigger.js
@@ -90,13 +90,18 @@
this.change
);
- Promise.all([this.ownerService.isCodeOwnerEnabled(), this.ownerService.areAllFilesApproved()])
- .then(([enabled, approved]) => {
+ Promise.all([
+ this.ownerService.isCodeOwnerEnabled(),
+ this.ownerService.areAllFilesApproved(),
+ this.ownerService.getLoggedInUserInitialRole()
+ ])
+ .then(([enabled, approved, userRole]) => {
if (enabled) {
this.hidden = approved;
} else {
this.hidden = true;
}
+ this._userRole = userRole;
});
}
@@ -105,6 +110,7 @@
ownerState.expandSuggestion = this.expanded;
this.reporting.reportInteraction('toggle-suggest-owners', {
expanded: this.expanded,
+ user_role: this._userRole ? this._userRole : 'UNKNOWN',
});
}
@@ -121,4 +127,4 @@
}
}
-customElements.define(SuggestOwnersTrigger.is, SuggestOwnersTrigger);
\ No newline at end of file
+customElements.define(SuggestOwnersTrigger.is, SuggestOwnersTrigger);