@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.

Make "bin/audit delete" synchronize commit audit status, and improve "bin/audit synchronize" documentation

Summary:
Depends on D20126. See PHI1056. Ref T13244.

- `bin/audit delete` destroys audit requests, but does not update the overall audit state for associated commits. For example, if you destroy all audit requests for a commit, it does not move to "No Audit Required".
- `bin/audit synchronize` does this synchronize step, but is poorly documented.

Make `bin/audit delete` synchronize affected commits.

Document `bin/audit synchronize` better.

There's some reasonable argument that `bin/audit synchronize` perhaps shouldn't exist, but it does let you recover from an accidentally (or intentionally) mangled database state. For now, let it live.

Test Plan:
- Ran `bin/audit delete`, saw audits destroyed and affected commits synchornized.
- Ran `bin/audit synchronize`, saw behavior unchanged.
- Ran `bin/audit help`, got better help.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13244

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

+120 -73
+71 -35
src/applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php
··· 105 105 $query->withPHIDs(mpull($commits, 'getPHID')); 106 106 } 107 107 108 - $commits = $query->execute(); 109 - $commits = mpull($commits, null, 'getPHID'); 108 + $commit_iterator = new PhabricatorQueryIterator($query); 109 + 110 110 $audits = array(); 111 - foreach ($commits as $commit) { 111 + foreach ($commit_iterator as $commit) { 112 112 $commit_audits = $commit->getAudits(); 113 113 foreach ($commit_audits as $key => $audit) { 114 114 if ($id_map && empty($id_map[$audit->getID()])) { ··· 131 131 continue; 132 132 } 133 133 } 134 - $audits[] = $commit_audits; 135 - } 136 - $audits = array_mergev($audits); 137 134 138 - $console = PhutilConsole::getConsole(); 135 + if (!$commit_audits) { 136 + continue; 137 + } 139 138 140 - if (!$audits) { 141 - $console->writeErr("%s\n", pht('No audits match the query.')); 142 - return 0; 143 - } 139 + $handles = id(new PhabricatorHandleQuery()) 140 + ->setViewer($viewer) 141 + ->withPHIDs(mpull($commit_audits, 'getAuditorPHID')) 142 + ->execute(); 144 143 145 - $handles = id(new PhabricatorHandleQuery()) 146 - ->setViewer($this->getViewer()) 147 - ->withPHIDs(mpull($audits, 'getAuditorPHID')) 148 - ->execute(); 144 + foreach ($commit_audits as $audit) { 145 + $audit_id = $audit->getID(); 149 146 150 - 151 - foreach ($audits as $audit) { 152 - $commit = $commits[$audit->getCommitPHID()]; 153 - 154 - $console->writeOut( 155 - "%s\n", 156 - sprintf( 147 + $description = sprintf( 157 148 '%10d %-16s %-16s %s: %s', 158 - $audit->getID(), 149 + $audit_id, 159 150 $handles[$audit->getAuditorPHID()]->getName(), 160 151 PhabricatorAuditStatusConstants::getStatusName( 161 152 $audit->getAuditStatus()), 162 153 $commit->getRepository()->formatCommitName( 163 154 $commit->getCommitIdentifier()), 164 - trim($commit->getSummary()))); 155 + trim($commit->getSummary())); 156 + 157 + $audits[] = array( 158 + 'auditID' => $audit_id, 159 + 'commitPHID' => $commit->getPHID(), 160 + 'description' => $description, 161 + ); 162 + } 165 163 } 166 164 167 - if (!$is_dry_run) { 168 - $message = pht( 169 - 'Really delete these %d audit(s)? They will be permanently deleted '. 170 - 'and can not be recovered.', 171 - count($audits)); 172 - if ($console->confirm($message)) { 173 - foreach ($audits as $audit) { 174 - $id = $audit->getID(); 175 - $console->writeOut("%s\n", pht('Deleting audit %d...', $id)); 176 - $audit->delete(); 177 - } 165 + if (!$audits) { 166 + echo tsprintf( 167 + "%s\n", 168 + pht('No audits match the query.')); 169 + return 0; 170 + } 171 + 172 + foreach ($audits as $audit_spec) { 173 + echo tsprintf( 174 + "%s\n", 175 + $audit_spec['description']); 176 + } 177 + 178 + if ($is_dry_run) { 179 + echo tsprintf( 180 + "%s\n", 181 + pht('This is a dry run, so no changes will be made.')); 182 + return 0; 183 + } 184 + 185 + $message = pht( 186 + 'Really delete these %s audit(s)? They will be permanently deleted '. 187 + 'and can not be recovered.', 188 + phutil_count($audits)); 189 + if (!phutil_console_confirm($message)) { 190 + echo tsprintf( 191 + "%s\n", 192 + pht('User aborted the workflow.')); 193 + return 1; 194 + } 195 + 196 + $audits_by_commit = igroup($audits, 'commitPHID'); 197 + foreach ($audits_by_commit as $commit_phid => $audit_specs) { 198 + $audit_ids = ipull($audit_specs, 'auditID'); 199 + 200 + $audits = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere( 201 + 'id IN (%Ld)', 202 + $audit_ids); 203 + 204 + foreach ($audits as $audit) { 205 + $id = $audit->getID(); 206 + 207 + echo tsprintf( 208 + "%s\n", 209 + pht('Deleting audit %d...', $id)); 210 + 211 + $audit->delete(); 178 212 } 213 + 214 + $this->synchronizeCommitAuditState($commit_phid); 179 215 } 180 216 181 217 return 0;
+35
src/applications/audit/management/PhabricatorAuditManagementWorkflow.php
··· 87 87 return $commits; 88 88 } 89 89 90 + protected function synchronizeCommitAuditState($commit_phid) { 91 + $viewer = $this->getViewer(); 92 + 93 + $commit = id(new DiffusionCommitQuery()) 94 + ->setViewer($viewer) 95 + ->withPHIDs(array($commit_phid)) 96 + ->needAuditRequests(true) 97 + ->executeOne(); 98 + if (!$commit) { 99 + return; 100 + } 101 + 102 + $old_status = $commit->getAuditStatusObject(); 103 + $commit->updateAuditStatus($commit->getAudits()); 104 + $new_status = $commit->getAuditStatusObject(); 105 + 106 + if ($old_status->getKey() == $new_status->getKey()) { 107 + echo tsprintf( 108 + "%s\n", 109 + pht( 110 + 'No synchronization changes for "%s".', 111 + $commit->getDisplayName())); 112 + } else { 113 + echo tsprintf( 114 + "%s\n", 115 + pht( 116 + 'Synchronizing "%s": "%s" -> "%s".', 117 + $commit->getDisplayName(), 118 + $old_status->getName(), 119 + $new_status->getName())); 120 + 121 + $commit->save(); 122 + } 123 + } 124 + 90 125 }
+11 -32
src/applications/audit/management/PhabricatorAuditSynchronizeManagementWorkflow.php
··· 6 6 protected function didConstruct() { 7 7 $this 8 8 ->setName('synchronize') 9 - ->setExamples('**synchronize** ...') 10 - ->setSynopsis(pht('Update audit status for commits.')) 9 + ->setExamples( 10 + "**synchronize** __repository__ ...\n". 11 + "**synchronize** __commit__ ...\n". 12 + "**synchronize** --all") 13 + ->setSynopsis( 14 + pht( 15 + 'Update commits to make their summary audit state reflect the '. 16 + 'state of their actual audit requests. This can fix inconsistencies '. 17 + 'in database state if audit requests have been mangled '. 18 + 'accidentally (or on purpose).')) 11 19 ->setArguments( 12 20 array_merge( 13 21 $this->getCommitConstraintArguments(), ··· 21 29 foreach ($objects as $object) { 22 30 $commits = $this->loadCommitsForConstraintObject($object); 23 31 foreach ($commits as $commit) { 24 - $commit = id(new DiffusionCommitQuery()) 25 - ->setViewer($viewer) 26 - ->withPHIDs(array($commit->getPHID())) 27 - ->needAuditRequests(true) 28 - ->executeOne(); 29 - if (!$commit) { 30 - continue; 31 - } 32 - 33 - $old_status = $commit->getAuditStatusObject(); 34 - $commit->updateAuditStatus($commit->getAudits()); 35 - $new_status = $commit->getAuditStatusObject(); 36 - 37 - if ($old_status->getKey() == $new_status->getKey()) { 38 - echo tsprintf( 39 - "%s\n", 40 - pht( 41 - 'No changes for "%s".', 42 - $commit->getDisplayName())); 43 - } else { 44 - echo tsprintf( 45 - "%s\n", 46 - pht( 47 - 'Updating "%s": "%s" -> "%s".', 48 - $commit->getDisplayName(), 49 - $old_status->getName(), 50 - $new_status->getName())); 51 - 52 - $commit->save(); 53 - } 32 + $this->synchronizeCommitAuditState($commit->getPHID()); 54 33 } 55 34 } 56 35 }
+3 -6
src/docs/user/userguide/audit.diviner
··· 175 175 incorrectly (for example, because a package or Herald rule was configured in an 176 176 overbroad way). 177 177 178 - After deleting audits, you may want to run `bin/audit synchronize` to 179 - synchronize audit state. 180 - 181 178 **Synchronize Audit State**: Synchronize the audit state of commits to the 182 179 current open audit requests with `bin/audit synchronize`. 183 180 184 181 Normally, overall audit state is automatically kept up to date as changes are 185 - made to an audit. However, if you delete audits or manually update the database 186 - to make changes to audit request state, the state of corresponding commits may 187 - no longer be correct. 182 + made to an audit. However, if you manually update the database to make changes 183 + to audit request state, the state of corresponding commits may no longer be 184 + consistent. 188 185 189 186 This command will update commits so their overall audit state reflects the 190 187 cumulative state of their actual audit requests.