mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-10 14:51:06 +01:00
(stable) Promote 2018 Week 32
This commit is contained in:
commit
b348fb1b55
9 changed files with 263 additions and 89 deletions
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Advise installs to rebuild the repository identities.
|
||||||
|
|
||||||
|
// If the install has no commits (or no commits that lack an
|
||||||
|
// authorIdentityPHID), don't require a rebuild.
|
||||||
|
$commits = id(new PhabricatorRepositoryCommit())
|
||||||
|
->loadAllWhere('authorIdentityPHID IS NULL LIMIT 1');
|
||||||
|
|
||||||
|
if (!$commits) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
id(new PhabricatorConfigManualActivity())
|
||||||
|
->setActivityType(PhabricatorConfigManualActivity::TYPE_IDENTITIES)
|
||||||
|
->save();
|
||||||
|
} catch (AphrontDuplicateKeyQueryException $ex) {
|
||||||
|
// If we've already noted that this activity is required, just move on.
|
||||||
|
}
|
|
@ -2,13 +2,27 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$root = dirname(dirname(dirname(__FILE__)));
|
$root = dirname(dirname(dirname(__FILE__)));
|
||||||
require_once $root.'/scripts/__init_script__.php';
|
require_once $root.'/scripts/init/init-script.php';
|
||||||
|
|
||||||
|
// NOTE: We are caching a datastructure rather than the flat key file because
|
||||||
|
// the path on disk to "ssh-exec" is arbitrarily mutable at runtime. See T12397.
|
||||||
|
|
||||||
$cache = PhabricatorCaches::getMutableCache();
|
$cache = PhabricatorCaches::getMutableCache();
|
||||||
$authfile_key = PhabricatorAuthSSHKeyQuery::AUTHFILE_CACHEKEY;
|
$authstruct_key = PhabricatorAuthSSHKeyQuery::AUTHSTRUCT_CACHEKEY;
|
||||||
$authfile = $cache->getKey($authfile_key);
|
$authstruct_raw = $cache->getKey($authstruct_key);
|
||||||
|
|
||||||
if ($authfile === null) {
|
$authstruct = null;
|
||||||
|
|
||||||
|
if (strlen($authstruct_raw)) {
|
||||||
|
try {
|
||||||
|
$authstruct = phutil_json_decode($authstruct_raw);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
// Ignore any issues with the cached data; we'll just rebuild the
|
||||||
|
// structure below.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($authstruct === null) {
|
||||||
$keys = id(new PhabricatorAuthSSHKeyQuery())
|
$keys = id(new PhabricatorAuthSSHKeyQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
->withIsActive(true)
|
->withIsActive(true)
|
||||||
|
@ -19,7 +33,7 @@ if ($authfile === null) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$bin = $root.'/bin/ssh-exec';
|
$key_list = array();
|
||||||
foreach ($keys as $ssh_key) {
|
foreach ($keys as $ssh_key) {
|
||||||
$key_argv = array();
|
$key_argv = array();
|
||||||
$object = $ssh_key->getObject();
|
$object = $ssh_key->getObject();
|
||||||
|
@ -42,18 +56,7 @@ if ($authfile === null) {
|
||||||
$key_argv[] = '--phabricator-ssh-key';
|
$key_argv[] = '--phabricator-ssh-key';
|
||||||
$key_argv[] = $ssh_key->getID();
|
$key_argv[] = $ssh_key->getID();
|
||||||
|
|
||||||
$cmd = csprintf('%s %Ls', $bin, $key_argv);
|
|
||||||
|
|
||||||
$instance = PhabricatorEnv::getEnvConfig('cluster.instance');
|
|
||||||
if (strlen($instance)) {
|
|
||||||
$cmd = csprintf('PHABRICATOR_INSTANCE=%s %C', $instance, $cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is additional escaping for the SSH 'command="..."' string.
|
|
||||||
$cmd = addcslashes($cmd, '"\\');
|
|
||||||
|
|
||||||
// Strip out newlines and other nonsense from the key type and key body.
|
// Strip out newlines and other nonsense from the key type and key body.
|
||||||
|
|
||||||
$type = $ssh_key->getKeyType();
|
$type = $ssh_key->getKeyType();
|
||||||
$type = preg_replace('@[\x00-\x20]+@', '', $type);
|
$type = preg_replace('@[\x00-\x20]+@', '', $type);
|
||||||
if (!strlen($type)) {
|
if (!strlen($type)) {
|
||||||
|
@ -66,6 +69,40 @@ if ($authfile === null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$key_list[] = array(
|
||||||
|
'argv' => $key_argv,
|
||||||
|
'type' => $type,
|
||||||
|
'key' => $key,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$authstruct = array(
|
||||||
|
'keys' => $key_list,
|
||||||
|
);
|
||||||
|
|
||||||
|
$authstruct_raw = phutil_json_encode($authstruct);
|
||||||
|
$ttl = phutil_units('24 hours in seconds');
|
||||||
|
$cache->setKey($authstruct_key, $authstruct_raw, $ttl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$bin = $root.'/bin/ssh-exec';
|
||||||
|
$instance = PhabricatorEnv::getEnvConfig('cluster.instance');
|
||||||
|
|
||||||
|
$lines = array();
|
||||||
|
foreach ($authstruct['keys'] as $key_struct) {
|
||||||
|
$key_argv = $key_struct['argv'];
|
||||||
|
$key = $key_struct['key'];
|
||||||
|
$type = $key_struct['type'];
|
||||||
|
|
||||||
|
$cmd = csprintf('%s %Ls', $bin, $key_argv);
|
||||||
|
|
||||||
|
if (strlen($instance)) {
|
||||||
|
$cmd = csprintf('PHABRICATOR_INSTANCE=%s %C', $instance, $cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is additional escaping for the SSH 'command="..."' string.
|
||||||
|
$cmd = addcslashes($cmd, '"\\');
|
||||||
|
|
||||||
$options = array(
|
$options = array(
|
||||||
'command="'.$cmd.'"',
|
'command="'.$cmd.'"',
|
||||||
'no-port-forwarding',
|
'no-port-forwarding',
|
||||||
|
@ -79,9 +116,7 @@ if ($authfile === null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$authfile = implode('', $lines);
|
$authfile = implode('', $lines);
|
||||||
$ttl = phutil_units('24 hours in seconds');
|
|
||||||
$cache->setKey($authfile_key, $authfile, $ttl);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo $authfile;
|
echo $authfile;
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
final class PhabricatorAuthSSHKeyQuery
|
final class PhabricatorAuthSSHKeyQuery
|
||||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
const AUTHFILE_CACHEKEY = 'ssh.authfile';
|
const AUTHSTRUCT_CACHEKEY = 'ssh.authstruct';
|
||||||
|
|
||||||
private $ids;
|
private $ids;
|
||||||
private $phids;
|
private $phids;
|
||||||
|
@ -13,7 +13,7 @@ final class PhabricatorAuthSSHKeyQuery
|
||||||
|
|
||||||
public static function deleteSSHKeyCache() {
|
public static function deleteSSHKeyCache() {
|
||||||
$cache = PhabricatorCaches::getMutableCache();
|
$cache = PhabricatorCaches::getMutableCache();
|
||||||
$authfile_key = self::AUTHFILE_CACHEKEY;
|
$authfile_key = self::AUTHSTRUCT_CACHEKEY;
|
||||||
$cache->deleteKey($authfile_key);
|
$cache->deleteKey($authfile_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,21 @@ final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
|
||||||
$cache = $info['cache_list'];
|
$cache = $info['cache_list'];
|
||||||
$state = array();
|
$state = array();
|
||||||
foreach ($cache as $item) {
|
foreach ($cache as $item) {
|
||||||
$info = idx($item, 'info', '<unknown-key>');
|
// Some older versions of APCu report the cachekey as "key", while
|
||||||
|
// newer APCu and APC report it as "info". Just check both indexes
|
||||||
|
// for commpatibility. See T13164 for details.
|
||||||
|
|
||||||
|
$info = idx($item, 'info');
|
||||||
|
if ($info === null) {
|
||||||
|
$info = idx($item, 'key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($info === null) {
|
||||||
|
$key = '<unknown-key>';
|
||||||
|
} else {
|
||||||
$key = self::getKeyPattern($info);
|
$key = self::getKeyPattern($info);
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($state[$key])) {
|
if (empty($state[$key])) {
|
||||||
$state[$key] = array(
|
$state[$key] = array(
|
||||||
'max' => 0,
|
'max' => 0,
|
||||||
|
|
|
@ -21,6 +21,13 @@ final class PhabricatorConduitCallManagementWorkflow
|
||||||
'File to read parameters from, or "-" to read from '.
|
'File to read parameters from, or "-" to read from '.
|
||||||
'stdin.'),
|
'stdin.'),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'as',
|
||||||
|
'param' => 'username',
|
||||||
|
'help' => pht(
|
||||||
|
'Execute the call as the given user. (If omitted, the call will '.
|
||||||
|
'be executed as an omnipotent user.)'),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +46,22 @@ final class PhabricatorConduitCallManagementWorkflow
|
||||||
pht('Specify a file to read parameters from with "--input".'));
|
pht('Specify a file to read parameters from with "--input".'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$as = $args->getArg('as');
|
||||||
|
if (strlen($as)) {
|
||||||
|
$actor = id(new PhabricatorPeopleQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withUsernames(array($as))
|
||||||
|
->executeOne();
|
||||||
|
if (!$actor) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'No such user "%s" exists.',
|
||||||
|
$as));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$actor = $viewer;
|
||||||
|
}
|
||||||
|
|
||||||
if ($input === '-') {
|
if ($input === '-') {
|
||||||
fprintf(STDERR, tsprintf("%s\n", pht('Reading input from stdin...')));
|
fprintf(STDERR, tsprintf("%s\n", pht('Reading input from stdin...')));
|
||||||
$input_json = file_get_contents('php://stdin');
|
$input_json = file_get_contents('php://stdin');
|
||||||
|
@ -49,7 +72,7 @@ final class PhabricatorConduitCallManagementWorkflow
|
||||||
$params = phutil_json_decode($input_json);
|
$params = phutil_json_decode($input_json);
|
||||||
|
|
||||||
$result = id(new ConduitCall($method, $params))
|
$result = id(new ConduitCall($method, $params))
|
||||||
->setUser($viewer)
|
->setUser($actor)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
$output = array(
|
$output = array(
|
||||||
|
|
|
@ -13,10 +13,21 @@ final class PhabricatorManualActivitySetupCheck
|
||||||
foreach ($activities as $activity) {
|
foreach ($activities as $activity) {
|
||||||
$type = $activity->getActivityType();
|
$type = $activity->getActivityType();
|
||||||
|
|
||||||
// For now, there is only one type of manual activity. It's not clear
|
switch ($type) {
|
||||||
// if we're really going to have too much more of this stuff so this
|
case PhabricatorConfigManualActivity::TYPE_REINDEX:
|
||||||
// is a bit under-designed for now.
|
$this->raiseSearchReindexIssue();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PhabricatorConfigManualActivity::TYPE_IDENTITIES:
|
||||||
|
$this->raiseRebuildIdentitiesIssue();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function raiseSearchReindexIssue() {
|
||||||
$activity_name = pht('Rebuild Search Index');
|
$activity_name = pht('Rebuild Search Index');
|
||||||
$activity_summary = pht(
|
$activity_summary = pht(
|
||||||
'The search index algorithm has been updated and the index needs '.
|
'The search index algorithm has been updated and the index needs '.
|
||||||
|
@ -60,16 +71,76 @@ final class PhabricatorManualActivitySetupCheck
|
||||||
$message[] = phutil_tag(
|
$message[] = phutil_tag(
|
||||||
'pre',
|
'pre',
|
||||||
array(),
|
array(),
|
||||||
(string)csprintf('phabricator/ $ ./bin/config done %R', $type));
|
'phabricator/ $ ./bin/config done reindex');
|
||||||
|
|
||||||
$activity_message = phutil_implode_html("\n\n", $message);
|
$activity_message = phutil_implode_html("\n\n", $message);
|
||||||
|
|
||||||
$this->newIssue('manual.'.$type)
|
$this->newIssue('manual.reindex')
|
||||||
|
->setName($activity_name)
|
||||||
|
->setSummary($activity_summary)
|
||||||
|
->setMessage($activity_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function raiseRebuildIdentitiesIssue() {
|
||||||
|
$activity_name = pht('Rebuild Repository Identities');
|
||||||
|
$activity_summary = pht(
|
||||||
|
'The mapping from VCS users to Phabricator users has changed '.
|
||||||
|
'and must be rebuilt.');
|
||||||
|
|
||||||
|
$message = array();
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'The way Phabricator attributes VCS activity to Phabricator users '.
|
||||||
|
'has changed. There is a new indirection layer between the strings '.
|
||||||
|
'that appear as VCS authors and committers (such as "John Developer '.
|
||||||
|
'<johnd@bigcorp.com>") and the Phabricator user that gets associated '.
|
||||||
|
'with VCS commits. This is to support situations where users '.
|
||||||
|
'are incorrectly associated with commits by Phabricator making bad '.
|
||||||
|
'guesses about the identity of the corresponding Phabricator user. '.
|
||||||
|
'This also helps with situations where existing repositories are '.
|
||||||
|
'imported without having created accounts for all the committers to '.
|
||||||
|
'that repository. Until you rebuild these repository identities, you '.
|
||||||
|
'are likely to encounter problems with future Phabricator features '.
|
||||||
|
'which will rely on the existence of these identities.');
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'You can rebuild repository identities while Phabricator is running.');
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'To rebuild identities, run this command:');
|
||||||
|
|
||||||
|
$message[] = phutil_tag(
|
||||||
|
'pre',
|
||||||
|
array(),
|
||||||
|
(string)csprintf(
|
||||||
|
'phabricator/ $ ./bin/repository rebuild-identities --all'));
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'You can find more information about this new identity mapping '.
|
||||||
|
'here: %s',
|
||||||
|
phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => 'https://phurl.io/u/repoIdentities',
|
||||||
|
'target' => '_blank',
|
||||||
|
),
|
||||||
|
'https://phurl.io/u/repoIdentities'));
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'After rebuilding repository identities, run this command to clear '.
|
||||||
|
'this setup warning:');
|
||||||
|
|
||||||
|
$message[] = phutil_tag(
|
||||||
|
'pre',
|
||||||
|
array(),
|
||||||
|
'phabricator/ $ ./bin/config done identities');
|
||||||
|
|
||||||
|
$activity_message = phutil_implode_html("\n\n", $message);
|
||||||
|
|
||||||
|
$this->newIssue('manual.identities')
|
||||||
->setName($activity_name)
|
->setName($activity_name)
|
||||||
->setSummary($activity_summary)
|
->setSummary($activity_summary)
|
||||||
->setMessage($activity_message);
|
->setMessage($activity_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ final class PhabricatorConfigManualActivity
|
||||||
protected $parameters = array();
|
protected $parameters = array();
|
||||||
|
|
||||||
const TYPE_REINDEX = 'reindex';
|
const TYPE_REINDEX = 'reindex';
|
||||||
|
const TYPE_IDENTITIES = 'identities';
|
||||||
|
|
||||||
|
|
||||||
protected function getConfiguration() {
|
protected function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
|
|
|
@ -206,7 +206,7 @@ final class PhabricatorRepositoryCommit
|
||||||
return $this->assertAttached($this->authorIdentity);
|
return $this->assertAttached($this->authorIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCommiterIdentity() {
|
public function getCommitterIdentity() {
|
||||||
return $this->assertAttached($this->committerIdentity);
|
return $this->assertAttached($this->committerIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,18 @@ final class PhabricatorStorageManagementProbeWorkflow
|
||||||
->setShowHeader(false)
|
->setShowHeader(false)
|
||||||
->setPadding(2)
|
->setPadding(2)
|
||||||
->addColumn('name', array('title' => pht('Database / Table')))
|
->addColumn('name', array('title' => pht('Database / Table')))
|
||||||
->addColumn('size', array('title' => pht('Size')))
|
->addColumn(
|
||||||
->addColumn('percentage', array('title' => pht('Percentage')));
|
'size',
|
||||||
|
array(
|
||||||
|
'title' => pht('Size'),
|
||||||
|
'align' => PhutilConsoleTable::ALIGN_RIGHT,
|
||||||
|
))
|
||||||
|
->addColumn(
|
||||||
|
'percentage',
|
||||||
|
array(
|
||||||
|
'title' => pht('Percentage'),
|
||||||
|
'align' => PhutilConsoleTable::ALIGN_RIGHT,
|
||||||
|
));
|
||||||
|
|
||||||
foreach ($totals as $db => $size) {
|
foreach ($totals as $db => $size) {
|
||||||
list($database_size, $database_percentage) = $this->formatSize(
|
list($database_size, $database_percentage) = $this->formatSize(
|
||||||
|
@ -98,7 +108,7 @@ final class PhabricatorStorageManagementProbeWorkflow
|
||||||
|
|
||||||
private function formatSize($n, $o) {
|
private function formatSize($n, $o) {
|
||||||
return array(
|
return array(
|
||||||
sprintf('%8.8s MB', number_format($n / (1024 * 1024), 1)),
|
pht('%s MB', new PhutilNumber($n / (1024 * 1024), 1)),
|
||||||
sprintf('%3.1f%%', 100 * ($n / $o)),
|
sprintf('%3.1f%%', 100 * ($n / $o)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue