Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add installer command #11

Merged
merged 32 commits into from Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
* Installer command for PHP & Laravel

## [1.3.0] - 2018-09-13
### Added
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Expand Up @@ -24,14 +24,16 @@
"php": "^7.1|^7.2",
"honeybadger-io/honeybadger-php": "^1.2",
"illuminate/console": "^5.5|^5.6",
"illuminate/support": "^5.5|^5.6"
"illuminate/support": "^5.5|^5.6",
"sixlive/dotenv-editor": "^1.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.10",
"larapack/dd": "^1.0",
"mockery/mockery": "^1.1",
"orchestra/testbench": "^3.5|^3.6|^3.7",
"phpunit/phpunit": "^6.0|^7.0"
"phpunit/phpunit": "^6.0|^7.0",
"sempro/phpunit-pretty-print": "^1.0"
},
"autoload": {
"psr-4": {
Expand Down
3 changes: 2 additions & 1 deletion phpunit.xml.dist
Expand Up @@ -8,7 +8,8 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
stopOnFailure="false"
printerClass="Sempro\PHPUnitPrettyPrinter\PrettyPrinter">
<testsuites>
<testsuite name="Honeybadger Test Suite">
<directory>tests</directory>
Expand Down
112 changes: 112 additions & 0 deletions src/CommandTasks.php
@@ -0,0 +1,112 @@
<?php

namespace Honeybadger\HoneybadgerLaravel;

use Illuminate\Support\Collection;
use Illuminate\Console\OutputStyle;
use Honeybadger\HoneybadgerLaravel\Exceptions\TaskFailed;

class CommandTasks
{
/**
* @var \Illuminate\Console\OutputStyle
*/
protected $output;

/**
* @var array
*/
protected $results = [];

/**
* @var array
*/
protected $tasks = [];

/**
* @var bool
*/
protected $throwOnError = true;

/**
* Set command output.
*
* @param \Illuminate\Console\OutputStyle $output
* @return self
*/
public function setOutput(OutputStyle $output) : self
{
$this->output = $output;

return $this;
}

/**
* Add task with result to the stack.
*
* @param string $name
* @param callable $task
* @return self
*/
public function addTask(string $name, callable $task) : self
{
$this->tasks[$name] = $task;

return $this;
}

/**
* Send tasks to the command output.
*
* @return void
*
* @throws \Honeybadger\HoneybadgerLaravel\TaskFailed
*/
public function runTasks() : void
{
Collection::make($this->tasks)->each(function ($task, $description) {
$result = $task();

if ($this->output) {
$this->output->writeLn(vsprintf('%s: %s', [
$description,
$result ? '<fg=green>✔</>' : '<fg=red>✘</>',
]));
}

$this->results[$description] = $result;

if (! $result && $this->throwOnError) {
throw new TaskFailed(sprintf('%s failed, please review output and try again.', $description));
}
});
}

/**
* Get all task results.
*
* @return array
*/
public function getResults() : array
{
return $this->results;
}

/**
* @return bool
*/
public function hasFailedTasks() : bool
{
return in_array(false, $this->results);
}

/**
* @return self
*/
public function doNotThrowOnError() : self
{
$this->throwOnError = false;

return $this;
}
}
20 changes: 16 additions & 4 deletions src/Commands/HoneybadgerCheckinCommand.php
Expand Up @@ -3,8 +3,8 @@
namespace Honeybadger\HoneybadgerLaravel\Commands;

use Exception;
use Honeybadger\Honeybadger;
use Illuminate\Console\Command;
use Honeybadger\Contracts\Reporter;

class HoneybadgerCheckinCommand extends Command
{
Expand All @@ -27,13 +27,25 @@ class HoneybadgerCheckinCommand extends Command
*
* @return mixed
*/
public function handle(Honeybadger $honeybadger)
public function handle(Reporter $honeybadger)
{
try {
$honeybadger->checkin($this->argument('id'));
$this->line(sprintf('Checkin %s was sent to Honeybadger', $this->argument('id')));
$honeybadger->checkin($this->apiKey());
$this->info(sprintf('Checkin %s was sent to Honeybadger', $this->argument('id')));
} catch (Exception $e) {
$this->error($e->getMessage());
}
}

/**
* Get the API key from input.
*
* @return string
*/
private function apiKey() : string
{
return is_array($this->argument('id'))
? $this->argument('id')[0]
: $this->argument('id');
}
}
183 changes: 183 additions & 0 deletions src/Commands/HoneybadgerInstallCommand.php
@@ -0,0 +1,183 @@
<?php

namespace Honeybadger\HoneybadgerLaravel\Commands;

use Honeybadger\Honeybadger;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Config;
use Honeybadger\Exceptions\ServiceException;
use Honeybadger\HoneybadgerLaravel\CommandTasks;
use Honeybadger\HoneybadgerLaravel\Contracts\Installer;
use Honeybadger\HoneybadgerLaravel\Exceptions\TaskFailed;
use Honeybadger\HoneybadgerLaravel\Concerns\RequiredInput;

class HoneybadgerInstallCommand extends Command
{
use RequiredInput;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'honeybadger:install {apiKey?}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Install and configure Honeybadger';

/**
* Configuration from gathered input.
*
* @var array
*/
protected $config = [];

/**
* @var \Honeybadger\HoneybadgerLaravel\Contracts\Installer;
*/
protected $installer;

/**
* @var \Honeybadger\HoneybadgerLaravel\CommandTasks
*/
protected $tasks;

/**
* Execute the console command.
*
* @return mixed
*/
public function handle(Installer $installer, CommandTasks $commandTasks)
{
$this->installer = $installer;
$this->tasks = $commandTasks;
$this->tasks->setOutput($this->output);

$this->config = $this->gatherConfig();

$this->writeEnv();

if ($this->installer->shouldPublishConfig()) {
$this->tasks->addTask(
'Publish the config file',
function () {
return $this->publishConfig();
}
);
}

$results = $this->sendTest();

try {
$this->tasks->runTasks();
$this->outputSuccessMessage(array_get($results ?? [], 'id', ''));
} catch (TaskFailed $e) {
$this->line('');
$this->error($e->getMessage());
}
}

/**
* Prompt for input and gather responses.
*
* @return array
*/
private function gatherConfig() : array
{
return [
'api_key' => $this->argument('apiKey') ?? $this->promptForApiKey(),
];
}

/**
* Prompt for the API key.
*
* @return string
*/
private function promptForApiKey() : string
{
return $this->requiredSecret('Your API key', 'The API key is required');
}

/**
* Send test exception to Honeybadger.
*
* @return array
*/
private function sendTest() : array
{
Config::set('honeybadger.api_key', $this->config['api_key']);

try {
$result = $this->installer->sendTestException();
} catch (ServiceException $e) {
$result = [];
}

$this->tasks->addTask(
'Send test exception to Honeybadger',
function () use ($result) {
return ! empty($result);
}
);

return $result;
}

/**
* Write configuration values to the env files.
*
* @return void
*/
private function writeEnv() : void
{
$this->tasks->addTask(
'Write HONEYBADGER_API_KEY to .env',
function () {
return $this->installer->writeConfig(
['HONEYBADGER_API_KEY' => $this->config['api_key']],
base_path('.env')
);
}
);

$this->tasks->addTask(
'Write HONEYBADGER_API_KEY placeholder to .env.example',
function () {
return $this->installer->writeConfig(
['HONEYBADGER_API_KEY' => ''],
base_path('.env.example')
);
}
);
}

/**
* Publish the config file for Lumen or Laravel.
*
* @return bool
*/
public function publishConfig() : bool
{
if (app('honeybadger.isLumen')) {
return $this->installer->publishLumenConfig();
}

return $this->installer->publishLaravelConfig();
}

/**
* Output the success message.
*
* @param string $noticeId
* @return void
*/
private function outputSuccessMessage(string $noticeId) : void
{
$this->line(SuccessMessage::make($noticeId));
}
}