1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-04 20:52:43 +01:00
phorge-phorge/src/applications/herald/adapter/HeraldCommitAdapter.php

235 lines
7 KiB
PHP
Raw Normal View History

<?php
final class HeraldCommitAdapter extends HeraldObjectAdapter {
protected $diff;
protected $revision;
protected $repository;
protected $commit;
protected $commitData;
protected $emailPHIDs = array();
Allow Herald to trigger audits for users or projects Summary: Allows you to write a commit rule that triggers an audit by a user (personal rules) or a project (global rules). Mostly this is trying to make auditing more lightweight and accessible in environments where setting up Owners packages doesn't make sense. For instance, Disqus wants a rule like "trigger an audit for everything that didn't have a Differential revision". While not necessarily scalable, this is a perfectly reasonable rule for a small company, but a lot of work to implement with Owners (and you'll get a lot of collateral damage if you don't make every committer a project owner). Instead, they can create a project called 'Unreviewed Commits' and write a rule like: - When: Differential revision does not exist - Action: Trigger an Audit for project: "Unreviewed Commits" Then whoever cares can join that project and they'll see those audits in their queue, and when they approve/raise on commits their actions will affect the project audit. Similarly, if I want to look at all commits that match some other rule (say, XSS) but only want to do it like once a month, I can just set up an audit rule and go through the queue when I feel like it. NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs. Through the magic of handles, this (apparently) works fine for now; I'll do a big schema patch soon but have several other edits I want to make at the same time. Also: - Adds an "active" fiew for /audit/, eventually this will be like the Differential "active" view (stuff that is relevant to you right now). - On commits, highlight triggered audits you are responsible for. Test Plan: Added personal and global audit triggers to Herald, reparsed some commits with --herald, got audits. Browsed all audit interfaces to make sure nothing exploded. Viewed a commit where I was responsible for only some audits. Performed audits and made sure the triggers I am supposed to be responsible for updated properly. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
protected $auditMap = array();
protected $affectedPaths;
protected $affectedRevision;
protected $affectedPackages;
protected $auditNeededPackages;
public function __construct(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $commit_data) {
$this->repository = $repository;
$this->commit = $commit;
$this->commitData = $commit_data;
}
public function getPHID() {
return $this->commit->getPHID();
}
public function getEmailPHIDs() {
2011-04-04 23:12:20 +02:00
return array_keys($this->emailPHIDs);
}
Allow Herald to trigger audits for users or projects Summary: Allows you to write a commit rule that triggers an audit by a user (personal rules) or a project (global rules). Mostly this is trying to make auditing more lightweight and accessible in environments where setting up Owners packages doesn't make sense. For instance, Disqus wants a rule like "trigger an audit for everything that didn't have a Differential revision". While not necessarily scalable, this is a perfectly reasonable rule for a small company, but a lot of work to implement with Owners (and you'll get a lot of collateral damage if you don't make every committer a project owner). Instead, they can create a project called 'Unreviewed Commits' and write a rule like: - When: Differential revision does not exist - Action: Trigger an Audit for project: "Unreviewed Commits" Then whoever cares can join that project and they'll see those audits in their queue, and when they approve/raise on commits their actions will affect the project audit. Similarly, if I want to look at all commits that match some other rule (say, XSS) but only want to do it like once a month, I can just set up an audit rule and go through the queue when I feel like it. NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs. Through the magic of handles, this (apparently) works fine for now; I'll do a big schema patch soon but have several other edits I want to make at the same time. Also: - Adds an "active" fiew for /audit/, eventually this will be like the Differential "active" view (stuff that is relevant to you right now). - On commits, highlight triggered audits you are responsible for. Test Plan: Added personal and global audit triggers to Herald, reparsed some commits with --herald, got audits. Browsed all audit interfaces to make sure nothing exploded. Viewed a commit where I was responsible for only some audits. Performed audits and made sure the triggers I am supposed to be responsible for updated properly. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
public function getAuditMap() {
return $this->auditMap;
}
public function getHeraldName() {
return
'r'.
$this->repository->getCallsign().
$this->commit->getCommitIdentifier();
}
public function getHeraldTypeName() {
return HeraldContentTypeConfig::CONTENT_TYPE_COMMIT;
}
public function loadAffectedPaths() {
if ($this->affectedPaths === null) {
$result = PhabricatorOwnerPathQuery::loadAffectedPaths(
$this->repository, $this->commit);
$this->affectedPaths = $result;
}
return $this->affectedPaths;
}
public function loadAffectedPackages() {
if ($this->affectedPackages === null) {
$packages = PhabricatorOwnersPackage::loadAffectedPackages(
$this->repository,
$this->loadAffectedPaths());
$this->affectedPackages = $packages;
}
return $this->affectedPackages;
}
public function loadAuditNeededPackage() {
if ($this->auditNeededPackages === null) {
$status_arr = array(
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
PhabricatorAuditStatusConstants::CONCERNED,
);
$requests = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere(
"commitPHID = %s AND auditStatus IN (%Ls)",
$this->commit->getPHID(),
$status_arr);
$packages = mpull($requests, 'getAuditorPHID');
$this->auditNeededPackages = $packages;
}
return $this->auditNeededPackages;
}
public function loadDifferentialRevision() {
if ($this->affectedRevision === null) {
$this->affectedRevision = false;
$data = $this->commitData;
$revision_id = $data->getCommitDetail('differential.revisionID');
if ($revision_id) {
$revision = id(new DifferentialRevision())->load($revision_id);
if ($revision) {
$revision->loadRelationships();
$this->affectedRevision = $revision;
}
}
}
return $this->affectedRevision;
}
private function loadCommitDiff() {
$drequest = DiffusionRequest::newFromDictionary(
array(
'repository' => $this->repository,
'commit' => $this->commit->getCommitIdentifier(),
));
$raw = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)
->setTimeout(60 * 60 * 15)
->setLinesOfContext(0)
->loadRawDiff();
$parser = new ArcanistDiffParser();
$changes = $parser->parseDiff($raw);
$diff = DifferentialDiff::newFromRawChanges($changes);
return $diff;
}
public function getHeraldField($field) {
$data = $this->commitData;
switch ($field) {
case HeraldFieldConfig::FIELD_BODY:
return $data->getCommitMessage();
case HeraldFieldConfig::FIELD_AUTHOR:
return $data->getCommitDetail('authorPHID');
case HeraldFieldConfig::FIELD_REVIEWER:
return $data->getCommitDetail('reviewerPHID');
case HeraldFieldConfig::FIELD_DIFF_FILE:
return $this->loadAffectedPaths();
case HeraldFieldConfig::FIELD_REPOSITORY:
return $this->repository->getPHID();
case HeraldFieldConfig::FIELD_DIFF_CONTENT:
try {
$diff = $this->loadCommitDiff();
} catch (Exception $ex) {
return array(
'<<< Failed to load diff, this may mean the change was '.
'unimaginably enormous. >>>');
}
$dict = array();
$lines = array();
$changes = $diff->getChangesets();
foreach ($changes as $change) {
$lines = array();
foreach ($change->getHunks() as $hunk) {
$lines[] = $hunk->makeChanges();
}
$dict[$change->getFilename()] = implode("\n", $lines);
}
return $dict;
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE:
$packages = $this->loadAffectedPackages();
return mpull($packages, 'getPHID');
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER:
$packages = $this->loadAffectedPackages();
$owners = PhabricatorOwnersOwner::loadAllForPackages($packages);
return mpull($owners, 'getUserPHID');
case HeraldFieldConfig::FIELD_NEED_AUDIT_FOR_PACKAGE:
return $this->loadAuditNeededPackage();
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVISION:
$revision = $this->loadDifferentialRevision();
if (!$revision) {
return null;
}
return $revision->getID();
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVIEWERS:
$revision = $this->loadDifferentialRevision();
if (!$revision) {
return array();
}
return $revision->getReviewers();
case HeraldFieldConfig::FIELD_DIFFERENTIAL_CCS:
$revision = $this->loadDifferentialRevision();
if (!$revision) {
return array();
}
return $revision->getCCPHIDs();
default:
throw new Exception("Invalid field '{$field}'.");
}
}
public function applyHeraldEffects(array $effects) {
assert_instances_of($effects, 'HeraldEffect');
Allow Herald to trigger audits for users or projects Summary: Allows you to write a commit rule that triggers an audit by a user (personal rules) or a project (global rules). Mostly this is trying to make auditing more lightweight and accessible in environments where setting up Owners packages doesn't make sense. For instance, Disqus wants a rule like "trigger an audit for everything that didn't have a Differential revision". While not necessarily scalable, this is a perfectly reasonable rule for a small company, but a lot of work to implement with Owners (and you'll get a lot of collateral damage if you don't make every committer a project owner). Instead, they can create a project called 'Unreviewed Commits' and write a rule like: - When: Differential revision does not exist - Action: Trigger an Audit for project: "Unreviewed Commits" Then whoever cares can join that project and they'll see those audits in their queue, and when they approve/raise on commits their actions will affect the project audit. Similarly, if I want to look at all commits that match some other rule (say, XSS) but only want to do it like once a month, I can just set up an audit rule and go through the queue when I feel like it. NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs. Through the magic of handles, this (apparently) works fine for now; I'll do a big schema patch soon but have several other edits I want to make at the same time. Also: - Adds an "active" fiew for /audit/, eventually this will be like the Differential "active" view (stuff that is relevant to you right now). - On commits, highlight triggered audits you are responsible for. Test Plan: Added personal and global audit triggers to Herald, reparsed some commits with --herald, got audits. Browsed all audit interfaces to make sure nothing exploded. Viewed a commit where I was responsible for only some audits. Performed audits and made sure the triggers I am supposed to be responsible for updated properly. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
$result = array();
foreach ($effects as $effect) {
$action = $effect->getAction();
switch ($action) {
case HeraldActionConfig::ACTION_NOTHING:
$result[] = new HeraldApplyTranscript(
$effect,
true,
'Great success at doing nothing.');
break;
case HeraldActionConfig::ACTION_EMAIL:
Allow Herald to trigger audits for users or projects Summary: Allows you to write a commit rule that triggers an audit by a user (personal rules) or a project (global rules). Mostly this is trying to make auditing more lightweight and accessible in environments where setting up Owners packages doesn't make sense. For instance, Disqus wants a rule like "trigger an audit for everything that didn't have a Differential revision". While not necessarily scalable, this is a perfectly reasonable rule for a small company, but a lot of work to implement with Owners (and you'll get a lot of collateral damage if you don't make every committer a project owner). Instead, they can create a project called 'Unreviewed Commits' and write a rule like: - When: Differential revision does not exist - Action: Trigger an Audit for project: "Unreviewed Commits" Then whoever cares can join that project and they'll see those audits in their queue, and when they approve/raise on commits their actions will affect the project audit. Similarly, if I want to look at all commits that match some other rule (say, XSS) but only want to do it like once a month, I can just set up an audit rule and go through the queue when I feel like it. NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs. Through the magic of handles, this (apparently) works fine for now; I'll do a big schema patch soon but have several other edits I want to make at the same time. Also: - Adds an "active" fiew for /audit/, eventually this will be like the Differential "active" view (stuff that is relevant to you right now). - On commits, highlight triggered audits you are responsible for. Test Plan: Added personal and global audit triggers to Herald, reparsed some commits with --herald, got audits. Browsed all audit interfaces to make sure nothing exploded. Viewed a commit where I was responsible for only some audits. Performed audits and made sure the triggers I am supposed to be responsible for updated properly. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
foreach ($effect->getTarget() as $phid) {
$this->emailPHIDs[$phid] = true;
}
$result[] = new HeraldApplyTranscript(
$effect,
true,
'Added address to email targets.');
break;
Allow Herald to trigger audits for users or projects Summary: Allows you to write a commit rule that triggers an audit by a user (personal rules) or a project (global rules). Mostly this is trying to make auditing more lightweight and accessible in environments where setting up Owners packages doesn't make sense. For instance, Disqus wants a rule like "trigger an audit for everything that didn't have a Differential revision". While not necessarily scalable, this is a perfectly reasonable rule for a small company, but a lot of work to implement with Owners (and you'll get a lot of collateral damage if you don't make every committer a project owner). Instead, they can create a project called 'Unreviewed Commits' and write a rule like: - When: Differential revision does not exist - Action: Trigger an Audit for project: "Unreviewed Commits" Then whoever cares can join that project and they'll see those audits in their queue, and when they approve/raise on commits their actions will affect the project audit. Similarly, if I want to look at all commits that match some other rule (say, XSS) but only want to do it like once a month, I can just set up an audit rule and go through the queue when I feel like it. NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs. Through the magic of handles, this (apparently) works fine for now; I'll do a big schema patch soon but have several other edits I want to make at the same time. Also: - Adds an "active" fiew for /audit/, eventually this will be like the Differential "active" view (stuff that is relevant to you right now). - On commits, highlight triggered audits you are responsible for. Test Plan: Added personal and global audit triggers to Herald, reparsed some commits with --herald, got audits. Browsed all audit interfaces to make sure nothing exploded. Viewed a commit where I was responsible for only some audits. Performed audits and made sure the triggers I am supposed to be responsible for updated properly. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
case HeraldActionConfig::ACTION_AUDIT:
foreach ($effect->getTarget() as $phid) {
if (empty($this->auditMap[$phid])) {
$this->auditMap[$phid] = array();
}
$this->auditMap[$phid][] = $effect->getRuleID();
}
$result[] = new HeraldApplyTranscript(
$effect,
true,
'Triggered an audit.');
break;
case HeraldActionConfig::ACTION_FLAG:
$result[] = parent::applyFlagEffect(
$effect,
$this->commit->getPHID());
Allow Herald to trigger audits for users or projects Summary: Allows you to write a commit rule that triggers an audit by a user (personal rules) or a project (global rules). Mostly this is trying to make auditing more lightweight and accessible in environments where setting up Owners packages doesn't make sense. For instance, Disqus wants a rule like "trigger an audit for everything that didn't have a Differential revision". While not necessarily scalable, this is a perfectly reasonable rule for a small company, but a lot of work to implement with Owners (and you'll get a lot of collateral damage if you don't make every committer a project owner). Instead, they can create a project called 'Unreviewed Commits' and write a rule like: - When: Differential revision does not exist - Action: Trigger an Audit for project: "Unreviewed Commits" Then whoever cares can join that project and they'll see those audits in their queue, and when they approve/raise on commits their actions will affect the project audit. Similarly, if I want to look at all commits that match some other rule (say, XSS) but only want to do it like once a month, I can just set up an audit rule and go through the queue when I feel like it. NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs. Through the magic of handles, this (apparently) works fine for now; I'll do a big schema patch soon but have several other edits I want to make at the same time. Also: - Adds an "active" fiew for /audit/, eventually this will be like the Differential "active" view (stuff that is relevant to you right now). - On commits, highlight triggered audits you are responsible for. Test Plan: Added personal and global audit triggers to Herald, reparsed some commits with --herald, got audits. Browsed all audit interfaces to make sure nothing exploded. Viewed a commit where I was responsible for only some audits. Performed audits and made sure the triggers I am supposed to be responsible for updated properly. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
break;
default:
throw new Exception("No rules to handle action '{$action}'.");
}
}
return $result;
}
}