mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 18:22:41 +01:00
Improve resolution process for nonfatal setup issues
Summary: - When a setup issue is nonfatal (i.e., a warning), instruct the user to edit the value from the web UI instead of using `bin/config`. - When the user edits configuration in response to a setup issue, send them back to the issue when they're done. - When an issue relates to PHP configuration, link to the PHP documentation on configuration. - Add new-style setup check for timezone issues. Test Plan: Mucked with my timezone config, resolved the issues I created. Reviewers: codeblock, btrahan, vrana Reviewed By: codeblock CC: aran Maniphest Tasks: T2221, T2228 Differential Revision: https://secure.phabricator.com/D4298
This commit is contained in:
parent
b852f213c3
commit
c32295aab6
9 changed files with 121 additions and 77 deletions
|
@ -3141,7 +3141,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'setup-issue-css' =>
|
'setup-issue-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/4214704f/rsrc/css/application/config/setup-issue.css',
|
'uri' => '/res/d642d4e5/rsrc/css/application/config/setup-issue.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -1143,6 +1143,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSetup' => 'infrastructure/PhabricatorSetup.php',
|
'PhabricatorSetup' => 'infrastructure/PhabricatorSetup.php',
|
||||||
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
|
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
|
||||||
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
|
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
|
||||||
|
'PhabricatorSetupCheckTimezone' => 'applications/config/check/PhabricatorSetupCheckTimezone.php',
|
||||||
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
||||||
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
||||||
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
|
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
|
||||||
|
@ -2426,6 +2427,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
|
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
|
||||||
|
'PhabricatorSetupCheckTimezone' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorSetupIssueView' => 'AphrontView',
|
'PhabricatorSetupIssueView' => 'AphrontView',
|
||||||
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
|
||||||
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
|
||||||
|
|
13
src/applications/cache/PhabricatorCaches.php
vendored
13
src/applications/cache/PhabricatorCaches.php
vendored
|
@ -28,9 +28,9 @@ final class PhabricatorCaches {
|
||||||
static $cache;
|
static $cache;
|
||||||
if (!$cache) {
|
if (!$cache) {
|
||||||
$caches = self::buildSetupCaches();
|
$caches = self::buildSetupCaches();
|
||||||
|
$caches = self::addProfilerToCaches($caches);
|
||||||
$cache = id(new PhutilKeyValueCacheStack())
|
$cache = id(new PhutilKeyValueCacheStack())
|
||||||
->setCaches($caches)
|
->setCaches($caches);
|
||||||
->setProfiler(PhutilServiceProfiler::getInstance());
|
|
||||||
}
|
}
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
|
@ -160,4 +160,13 @@ final class PhabricatorCaches {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function addProfilerToCaches(array $caches) {
|
||||||
|
foreach ($caches as $key => $cache) {
|
||||||
|
$pcache = new PhutilKeyValueCacheProfiler($cache);
|
||||||
|
$pcache->setProfiler(PhutilServiceProfiler::getInstance());
|
||||||
|
$caches[$key] = $pcache;
|
||||||
|
}
|
||||||
|
return $caches;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,6 @@ final class PhabricatorKeyValueDatabaseCache
|
||||||
const CACHE_FORMAT_DEFLATE = 'deflate';
|
const CACHE_FORMAT_DEFLATE = 'deflate';
|
||||||
|
|
||||||
public function setKeys(array $keys, $ttl = null) {
|
public function setKeys(array $keys, $ttl = null) {
|
||||||
$call_id = null;
|
|
||||||
if ($this->getProfiler()) {
|
|
||||||
$call_id = $this->getProfiler()->beginServiceCall(
|
|
||||||
array(
|
|
||||||
'type' => 'kvcache-set',
|
|
||||||
'name' => 'phabricator-db',
|
|
||||||
'keys' => array_keys($keys),
|
|
||||||
'ttl' => $ttl,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($keys) {
|
if ($keys) {
|
||||||
$map = $this->digestKeys(array_keys($keys));
|
$map = $this->digestKeys(array_keys($keys));
|
||||||
$conn_w = $this->establishConnection('w');
|
$conn_w = $this->establishConnection('w');
|
||||||
|
@ -58,24 +47,10 @@ final class PhabricatorKeyValueDatabaseCache
|
||||||
unset($guard);
|
unset($guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($call_id) {
|
|
||||||
$this->getProfiler()->endServiceCall($call_id, array());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getKeys(array $keys) {
|
public function getKeys(array $keys) {
|
||||||
$call_id = null;
|
|
||||||
if ($this->getProfiler()) {
|
|
||||||
$call_id = $this->getProfiler()->beginServiceCall(
|
|
||||||
array(
|
|
||||||
'type' => 'kvcache-get',
|
|
||||||
'name' => 'phabricator-db',
|
|
||||||
'keys' => $keys,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
if ($keys) {
|
if ($keys) {
|
||||||
$map = $this->digestKeys($keys);
|
$map = $this->digestKeys($keys);
|
||||||
|
@ -109,28 +84,10 @@ final class PhabricatorKeyValueDatabaseCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($call_id) {
|
|
||||||
$this->getProfiler()->endServiceCall(
|
|
||||||
$call_id,
|
|
||||||
array(
|
|
||||||
'hits' => array_keys($results),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteKeys(array $keys) {
|
public function deleteKeys(array $keys) {
|
||||||
$call_id = null;
|
|
||||||
if ($this->getProfiler()) {
|
|
||||||
$call_id = $this->getProfiler()->beginServiceCall(
|
|
||||||
array(
|
|
||||||
'type' => 'kvcache-del',
|
|
||||||
'name' => 'phabricator-db',
|
|
||||||
'keys' => $keys,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($keys) {
|
if ($keys) {
|
||||||
$map = $this->digestKeys($keys);
|
$map = $this->digestKeys($keys);
|
||||||
queryfx(
|
queryfx(
|
||||||
|
@ -140,10 +97,6 @@ final class PhabricatorKeyValueDatabaseCache
|
||||||
$keys);
|
$keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($call_id) {
|
|
||||||
$this->getProfiler()->endServiceCall($call_id, array());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSetupCheckTimezone extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
|
protected function executeChecks() {
|
||||||
|
$timezone = nonempty(
|
||||||
|
PhabricatorEnv::getEnvConfig('phabricator.timezone'),
|
||||||
|
ini_get('date.timezone'));
|
||||||
|
if ($timezone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$summary = pht(
|
||||||
|
"Without a configured timezone, PHP will emit warnings when working ".
|
||||||
|
"with dates, and dates and times may not display correctly.");
|
||||||
|
|
||||||
|
$message = pht(
|
||||||
|
"Your configuration fails to specify a server timezone. You can either ".
|
||||||
|
"set the PHP configuration value 'date.timezone' or the Phabricator ".
|
||||||
|
"configuration value 'phabricator.timezone' to specify one.");
|
||||||
|
|
||||||
|
$this
|
||||||
|
->newIssue('config.timezone')
|
||||||
|
->setShortName(pht('Timezone'))
|
||||||
|
->setName(pht('Server Timezone Not Configured'))
|
||||||
|
->setSummary($summary)
|
||||||
|
->setMessage($message)
|
||||||
|
->addPHPConfig('date.timezone')
|
||||||
|
->addPhabricatorConfig('phabricator.timezone');
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,14 @@ final class PhabricatorConfigEditController
|
||||||
$group = $option->getGroup();
|
$group = $option->getGroup();
|
||||||
$group_uri = $this->getApplicationURI('group/'.$group->getKey().'/');
|
$group_uri = $this->getApplicationURI('group/'.$group->getKey().'/');
|
||||||
|
|
||||||
|
$issue = $request->getStr('issue');
|
||||||
|
if ($issue) {
|
||||||
|
// If the user came here from an open setup issue, send them back.
|
||||||
|
$done_uri = $this->getApplicationURI('issue/'.$issue.'/');
|
||||||
|
} else {
|
||||||
|
$done_uri = $group_uri;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: This isn't quite correct -- we should read from the entire
|
// TODO: This isn't quite correct -- we should read from the entire
|
||||||
// configuration stack, ignoring database configuration. For now, though,
|
// configuration stack, ignoring database configuration. For now, though,
|
||||||
// it's a reasonable approximation.
|
// it's a reasonable approximation.
|
||||||
|
@ -62,7 +70,7 @@ final class PhabricatorConfigEditController
|
||||||
} else {
|
} else {
|
||||||
// TODO: When we do Transactions, make this just set isDeleted = 1
|
// TODO: When we do Transactions, make this just set isDeleted = 1
|
||||||
$config_entry->delete();
|
$config_entry->delete();
|
||||||
return id(new AphrontRedirectResponse())->setURI($group_uri);
|
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
$config_entry->setValue($value);
|
$config_entry->setValue($value);
|
||||||
|
@ -70,7 +78,7 @@ final class PhabricatorConfigEditController
|
||||||
|
|
||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
$config_entry->save();
|
$config_entry->save();
|
||||||
return id(new AphrontRedirectResponse())->setURI($group_uri);
|
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +96,7 @@ final class PhabricatorConfigEditController
|
||||||
|
|
||||||
$form
|
$form
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
|
->addHiddenInput('issue', $request->getStr('issue'))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextAreaControl())
|
id(new AphrontFormTextAreaControl())
|
||||||
->setLabel('JSON Value')
|
->setLabel('JSON Value')
|
||||||
|
@ -98,7 +107,7 @@ final class PhabricatorConfigEditController
|
||||||
->setName('value'))
|
->setName('value'))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->addCancelButton($group_uri)
|
->addCancelButton($done_uri)
|
||||||
->setValue(pht('Save Config Entry')))
|
->setValue(pht('Save Config Entry')))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
phutil_render_tag(
|
phutil_render_tag(
|
||||||
|
|
|
@ -23,16 +23,16 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
),
|
),
|
||||||
nl2br(phutil_escape_html($issue->getMessage())));
|
nl2br(phutil_escape_html($issue->getMessage())));
|
||||||
|
|
||||||
$configs = $issue->getPhabricatorConfig();
|
|
||||||
if ($configs) {
|
|
||||||
$description .= $this->renderPhabricatorConfig($configs);
|
|
||||||
}
|
|
||||||
|
|
||||||
$configs = $issue->getPHPConfig();
|
$configs = $issue->getPHPConfig();
|
||||||
if ($configs) {
|
if ($configs) {
|
||||||
$description .= $this->renderPHPConfig($configs);
|
$description .= $this->renderPHPConfig($configs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$configs = $issue->getPhabricatorConfig();
|
||||||
|
if ($configs) {
|
||||||
|
$description .= $this->renderPhabricatorConfig($configs);
|
||||||
|
}
|
||||||
|
|
||||||
$commands = $issue->getCommands();
|
$commands = $issue->getCommands();
|
||||||
if ($commands) {
|
if ($commands) {
|
||||||
$run_these = pht("Run these %d command(s):", count($commands));
|
$run_these = pht("Run these %d command(s):", count($commands));
|
||||||
|
@ -111,6 +111,8 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderPhabricatorConfig(array $configs) {
|
private function renderPhabricatorConfig(array $configs) {
|
||||||
|
$issue = $this->getIssue();
|
||||||
|
|
||||||
$table_info = phutil_render_tag(
|
$table_info = phutil_render_tag(
|
||||||
'p',
|
'p',
|
||||||
array(),
|
array(),
|
||||||
|
@ -141,10 +143,10 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
$table = phutil_render_tag(
|
$table = phutil_render_tag(
|
||||||
'table',
|
'table',
|
||||||
array(
|
array(
|
||||||
|
|
||||||
),
|
),
|
||||||
implode("\n", $table));
|
implode("\n", $table));
|
||||||
|
|
||||||
|
if ($this->getIssue()->getIsFatal()) {
|
||||||
$update_info = phutil_render_tag(
|
$update_info = phutil_render_tag(
|
||||||
'p',
|
'p',
|
||||||
array(),
|
array(),
|
||||||
|
@ -161,6 +163,23 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
$update[] = $cmd;
|
$update[] = $cmd;
|
||||||
}
|
}
|
||||||
$update = phutil_render_tag('pre', array(), implode("\n", $update));
|
$update = phutil_render_tag('pre', array(), implode("\n", $update));
|
||||||
|
} else {
|
||||||
|
$update_info = phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht("You can update these %d value(s) here:", count($configs)));
|
||||||
|
$update = array();
|
||||||
|
foreach ($configs as $config) {
|
||||||
|
$link = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/config/edit/'.$config.'/?issue='.$issue->getIssueKey(),
|
||||||
|
),
|
||||||
|
pht('Edit %s', phutil_escape_html($config)));
|
||||||
|
$update[] = '<li>'.$link.'</li>';
|
||||||
|
}
|
||||||
|
$update = '<ul>'.implode("\n", $update).'</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'div',
|
'div',
|
||||||
|
@ -276,8 +295,21 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
'p',
|
'p',
|
||||||
array(),
|
array(),
|
||||||
pht(
|
pht(
|
||||||
"After editing the PHP configuration, <strong>restart your webserver ".
|
"You can find more information about PHP configuration values in the ".
|
||||||
"for the changes to take effect</strong>."));
|
"%s.",
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => 'http://php.net/manual/ini.list.php',
|
||||||
|
),
|
||||||
|
pht('PHP Documentation'))));
|
||||||
|
|
||||||
|
$info .= phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"After editing the PHP configuration, <strong>restart your ".
|
||||||
|
"webserver for the changes to take effect</strong>."));
|
||||||
|
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'div',
|
'div',
|
||||||
|
|
|
@ -124,8 +124,10 @@ final class PhabricatorPasteQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadContent(array $pastes) {
|
private function loadContent(array $pastes) {
|
||||||
$cache = id(new PhabricatorKeyValueDatabaseCache())
|
$cache = new PhabricatorKeyValueDatabaseCache();
|
||||||
->setProfiler(PhutilServiceProfiler::getInstance());
|
|
||||||
|
$cache = new PhutilKeyValueCacheProfiler($cache);
|
||||||
|
$cache->setProfiler(PhutilServiceProfiler::getInstance());
|
||||||
|
|
||||||
$keys = array();
|
$keys = array();
|
||||||
foreach ($pastes as $paste) {
|
foreach ($pastes as $paste) {
|
||||||
|
|
|
@ -84,3 +84,9 @@
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.setup-issue ul {
|
||||||
|
width: 90%;
|
||||||
|
margin: 1em auto;
|
||||||
|
list-style: circle;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue