@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update Owners auditing rules for multiple reviewers

Summary:
Ref T10939. Fixes T10181. This slightly simplifies, then documents the auditing rules, which haven't been updated for a while. In particular:

- If an owner authored the change, never audit.
- Examine all reviewers to determine reviewer audit status, not just the first reviewer.
- Simplify some of the loading code a bit.

Test Plan:
- Ran `bin/repository reparse --owners <commit> --force` to trigger this stuff.
- Verified that the web UI did reasonable things with resulting audits.
- Read documentation.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10181, T10939

Differential Revision: https://secure.phabricator.com/D15939

+119 -71
+95 -71
src/applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php
··· 33 33 $repository, 34 34 $commit, 35 35 PhabricatorUser::getOmnipotentUser()); 36 + 36 37 $affected_packages = PhabricatorOwnersPackage::loadAffectedPackages( 37 38 $repository, 38 39 $affected_paths); 39 40 40 - if ($affected_packages) { 41 - $requests = id(new PhabricatorRepositoryAuditRequest()) 42 - ->loadAllWhere( 43 - 'commitPHID = %s', 44 - $commit->getPHID()); 45 - $requests = mpull($requests, null, 'getAuditorPHID'); 41 + if (!$affected_packages) { 42 + return; 43 + } 46 44 47 - foreach ($affected_packages as $package) { 48 - $request = idx($requests, $package->getPHID()); 49 - if ($request) { 50 - // Don't update request if it exists already. 51 - continue; 52 - } 45 + $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere( 46 + 'commitID = %d', 47 + $commit->getID()); 48 + $commit->attachCommitData($data); 53 49 54 - if ($package->isArchived()) { 55 - // Don't trigger audits if the package is archived. 56 - continue; 57 - } 50 + $author_phid = $data->getCommitDetail('authorPHID'); 51 + $revision_id = $data->getCommitDetail('differential.revisionID'); 52 + if ($revision_id) { 53 + $revision = id(new DifferentialRevisionQuery()) 54 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 55 + ->withIDs(array($revision_id)) 56 + ->needReviewerStatus(true) 57 + ->executeOne(); 58 + } else { 59 + $revision = null; 60 + } 58 61 59 - if ($package->getAuditingEnabled()) { 60 - $reasons = $this->checkAuditReasons($commit, $package); 61 - if ($reasons) { 62 - $audit_status = 63 - PhabricatorAuditStatusConstants::AUDIT_REQUIRED; 64 - } else { 65 - $audit_status = 66 - PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED; 67 - } 68 - } else { 69 - $reasons = array(); 70 - $audit_status = PhabricatorAuditStatusConstants::NONE; 71 - } 62 + $requests = id(new PhabricatorRepositoryAuditRequest()) 63 + ->loadAllWhere( 64 + 'commitPHID = %s', 65 + $commit->getPHID()); 66 + $requests = mpull($requests, null, 'getAuditorPHID'); 72 67 73 - $relationship = new PhabricatorRepositoryAuditRequest(); 74 - $relationship->setAuditorPHID($package->getPHID()); 75 - $relationship->setCommitPHID($commit->getPHID()); 76 - $relationship->setAuditReasons($reasons); 77 - $relationship->setAuditStatus($audit_status); 78 68 79 - $relationship->save(); 69 + foreach ($affected_packages as $package) { 70 + $request = idx($requests, $package->getPHID()); 71 + if ($request) { 72 + // Don't update request if it exists already. 73 + continue; 74 + } 80 75 81 - $requests[$package->getPHID()] = $relationship; 76 + if ($package->isArchived()) { 77 + // Don't trigger audits if the package is archived. 78 + continue; 82 79 } 83 80 84 - $commit->updateAuditStatus($requests); 85 - $commit->save(); 81 + if ($package->getAuditingEnabled()) { 82 + $reasons = $this->checkAuditReasons( 83 + $commit, 84 + $package, 85 + $author_phid, 86 + $revision); 87 + 88 + if ($reasons) { 89 + $audit_status = PhabricatorAuditStatusConstants::AUDIT_REQUIRED; 90 + } else { 91 + $audit_status = PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED; 92 + } 93 + } else { 94 + $reasons = array(); 95 + $audit_status = PhabricatorAuditStatusConstants::NONE; 96 + } 97 + 98 + $relationship = new PhabricatorRepositoryAuditRequest(); 99 + $relationship->setAuditorPHID($package->getPHID()); 100 + $relationship->setCommitPHID($commit->getPHID()); 101 + $relationship->setAuditReasons($reasons); 102 + $relationship->setAuditStatus($audit_status); 103 + 104 + $relationship->save(); 105 + 106 + $requests[$package->getPHID()] = $relationship; 86 107 } 108 + 109 + $commit->updateAuditStatus($requests); 110 + $commit->save(); 87 111 } 88 112 89 113 private function checkAuditReasons( 90 114 PhabricatorRepositoryCommit $commit, 91 - PhabricatorOwnersPackage $package) { 115 + PhabricatorOwnersPackage $package, 116 + $author_phid, 117 + $revision) { 92 118 93 - $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere( 94 - 'commitID = %d', 95 - $commit->getID()); 119 + $owner_phids = PhabricatorOwnersOwner::loadAffiliatedUserPHIDs( 120 + array( 121 + $package->getID(), 122 + )); 123 + $owner_phids = array_fuse($owner_phids); 96 124 97 125 $reasons = array(); 98 126 99 - if ($data->getCommitDetail('vsDiff')) { 100 - $reasons[] = pht('Changed After Revision Was Accepted'); 127 + if (!$author_phid) { 128 + $reasons[] = pht('Commit Author Not Recognized'); 129 + } else if (isset($owner_phids[$author_phid])) { 130 + return $reasons; 101 131 } 102 132 103 - $commit_author_phid = $data->getCommitDetail('authorPHID'); 104 - if (!$commit_author_phid) { 105 - $reasons[] = pht('Commit Author Not Recognized'); 133 + if (!$revision) { 134 + $reasons[] = pht('No Revision Specified'); 135 + return $reasons; 106 136 } 107 137 108 - $revision_id = $data->getCommitDetail('differential.revisionID'); 138 + $accepted_statuses = array( 139 + DifferentialReviewerStatus::STATUS_ACCEPTED, 140 + DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER, 141 + ); 142 + $accepted_statuses = array_fuse($accepted_statuses); 109 143 110 - $revision_author_phid = null; 111 - $commit_reviewedby_phid = null; 144 + $found_accept = false; 145 + foreach ($revision->getReviewerStatus() as $reviewer) { 146 + $reviewer_phid = $reviewer->getReviewerPHID(); 112 147 113 - if ($revision_id) { 114 - $revision = id(new DifferentialRevisionQuery()) 115 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 116 - ->withIDs(array($revision_id)) 117 - ->executeOne(); 118 - if ($revision) { 119 - $revision_author_phid = $revision->getAuthorPHID(); 120 - $commit_reviewedby_phid = $data->getCommitDetail('reviewerPHID'); 121 - if ($revision_author_phid !== $commit_author_phid) { 122 - $reasons[] = pht('Author Not Matching with Revision'); 123 - } 124 - } else { 125 - $reasons[] = pht('Revision Not Found'); 148 + // If this reviewer isn't a package owner, just ignore them. 149 + if (empty($owner_phids[$reviewer_phid])) { 150 + continue; 126 151 } 127 152 128 - } else { 129 - $reasons[] = pht('No Revision Specified'); 153 + // If this reviewer accepted the revision and owns the package, we're 154 + // all clear and do not need to trigger an audit. 155 + if (isset($accepted_statuses[$reviewer->getStatus()])) { 156 + $found_accept = true; 157 + break; 158 + } 130 159 } 131 160 132 - $owners_phids = PhabricatorOwnersOwner::loadAffiliatedUserPHIDs( 133 - array($package->getID())); 134 - 135 - if (!($commit_author_phid && in_array($commit_author_phid, $owners_phids) || 136 - $commit_reviewedby_phid && in_array($commit_reviewedby_phid, 137 - $owners_phids))) { 161 + if (!$found_accept) { 138 162 $reasons[] = pht('Owners Not Involved'); 139 163 } 140 164
+24
src/docs/user/userguide/owners.diviner
··· 98 98 NOTE: These rules **do not trigger** if the change author is a package owner. 99 99 They only apply to changes made by users who aren't already owners. 100 100 101 + These rules also do not trigger if the package has been archived. 102 + 101 103 The intent of this feature is to make it easy to configure simple, reasonable 102 104 behaviors. If you want more tailored or specific triggers, you can write more 103 105 powerful rules by using Herald. 106 + 107 + 108 + Auditing 109 + ======== 110 + 111 + You can automatically trigger audits on unreviewed code by configuring 112 + **Auditing**. The available settings are: 113 + 114 + - **Disabled**: Do not trigger audits. 115 + - **Enabled**: Trigger audits. 116 + 117 + When enabled, audits are triggered for commits which: 118 + 119 + - affect code owned by the package; 120 + - were not authored by a package owner; and 121 + - were not accepted by a package owner. 122 + 123 + Audits do not trigger if the package has been archived. 124 + 125 + The intent of this feature is to make it easy to configure simple auditing 126 + behavior. If you want more powerful auditing behavior, you can use Herald to 127 + write more sophisticated rules. 104 128 105 129 106 130 Files in Multiple Packages