Skip to content

Commit fffce2e

Browse files
author
Andrii Afanasiev
committed
add deploy command
1 parent a101bfb commit fffce2e

File tree

14 files changed

+635
-8
lines changed

14 files changed

+635
-8
lines changed

Command/AbstractCommand.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Command;
4+
5+
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
6+
use Symfony\Component\Console\Input\InputInterface;
7+
use Symfony\Component\Console\Output\ConsoleOutputInterface;
8+
use Symfony\Component\Console\Output\OutputInterface;
9+
use Symfony\Component\Console\Style\SymfonyStyle;
10+
11+
/**
12+
* Class AbstractCommand
13+
*
14+
* @package SymfonyRollbarBundle\Command
15+
*/
16+
abstract class AbstractCommand extends ContainerAwareCommand
17+
{
18+
/**
19+
* @var \Symfony\Component\Console\Style\SymfonyStyle
20+
*/
21+
protected $io;
22+
23+
/**
24+
* Extend the initialize method to add additional parameters to the class.
25+
*
26+
* {@inheritdoc}
27+
*/
28+
public function initialize(InputInterface $input, OutputInterface $output)
29+
{
30+
parent::initialize($input, $output);
31+
32+
$io = new SymfonyStyle($input, $output);
33+
$this->io = $io;
34+
}
35+
}

Command/DeployCommand.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Command;
4+
5+
use Symfony\Component\Console\Input\InputArgument;
6+
use Symfony\Component\Console\Input\InputInterface;
7+
use Symfony\Component\Console\Input\InputOption;
8+
use Symfony\Component\Console\Output\OutputInterface;
9+
10+
/**
11+
* Class DeployCommand
12+
*
13+
* @package SymfonyRollbarBundle\Command
14+
*/
15+
class DeployCommand extends \SymfonyRollbarBundle\Command\AbstractCommand
16+
{
17+
protected static $defaultName = 'rollbar:deploy';
18+
19+
/**
20+
* @inheritdoc
21+
*/
22+
protected function configure()
23+
{
24+
parent::configure();
25+
26+
$help = implode("\n", [
27+
'<info>%command.name%</info> - Track new build with Rollbar after successful deployment.',
28+
'See: <info>https://rollbar.com/docs/deploys_other</info>',
29+
]);
30+
31+
$this
32+
->setName(static::$defaultName)
33+
->setDescription('Send notification about new build.')
34+
->setHelp($help);
35+
36+
$this->addArgument(
37+
'revision',
38+
InputArgument::REQUIRED,
39+
'String identifying the revision being deployed, such as a Git SHA.');
40+
41+
$this->addOption(
42+
'comment',
43+
'c',
44+
InputOption::VALUE_OPTIONAL,
45+
'Additional text data to record with this deploy.'
46+
)->addOption(
47+
'rollbar_username',
48+
'ru',
49+
InputOption::VALUE_OPTIONAL,
50+
'Rollbar username of the user who deployed.'
51+
)->addOption(
52+
'local_username',
53+
'lu',
54+
InputOption::VALUE_OPTIONAL,
55+
'Username (on your system) who deployed.'
56+
);
57+
}
58+
59+
/**
60+
* @param \Symfony\Component\Console\Input\InputInterface $input
61+
* @param \Symfony\Component\Console\Output\OutputInterface $output
62+
*
63+
* @return int|null|void
64+
*/
65+
protected function execute(InputInterface $input, OutputInterface $output)
66+
{
67+
/** @var \SymfonyRollbarBundle\Provider\RollbarHandler $rbHandler */
68+
$rbHandler = $this->getContainer()->get('symfony_rollbar.provider.rollbar_handler');
69+
70+
$environment = $this->getContainer()->getParameter('kernel.environment');
71+
$revision = $input->getArgument('revision');
72+
$comment = $input->getOption('comment');
73+
$rUser = $input->getOption('rollbar_username');
74+
$lUser = $input->getOption('local_username');
75+
76+
$lUser = empty($lUser) ? get_current_user() : $lUser;
77+
78+
try {
79+
$rbHandler->trackBuild($environment, $revision, $comment, $rUser, $lUser);
80+
} catch (\GuzzleHttp\Exception\ClientException $e) {
81+
$this->io->error("Build has been not tracked:\n" . $e->getMessage());
82+
}
83+
84+
$this->io->success('Done.');
85+
}
86+
}

Provider/Api/Filter.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Provider\Api;
4+
5+
/**
6+
* Class Validator
7+
*
8+
* Before calls to API we have to check some restrictions on Rollbar side to avoid drops of request
9+
*
10+
* @package SymfonyRollbarBundle\Provider\Api
11+
*/
12+
class Filter
13+
{
14+
/**
15+
* @param mixed $value
16+
* @param string $filterName
17+
* @param array $options
18+
*
19+
* @return mixed
20+
*/
21+
public static function process($value, $filterName = '', $options = [])
22+
{
23+
$filter = new $filterName($options);
24+
25+
return $filter($value);
26+
}
27+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Provider\Api\Filter;
4+
5+
/**
6+
* Class AbstractFilter
7+
*
8+
* @package SymfonyRollbarBundle\Provider\Api\Filter
9+
*/
10+
abstract class AbstractFilter
11+
{
12+
/**
13+
* Do stuff with data
14+
*
15+
* @param $value
16+
*
17+
* @return mixed
18+
*/
19+
abstract public function __invoke($value);
20+
}

Provider/Api/Filter/Exception.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Provider\Api\Filter;
4+
5+
/**
6+
* Class Exception
7+
*
8+
* @package SymfonyRollbarBundle\Provider\Api\Filter
9+
*/
10+
class Exception extends \InvalidArgumentException
11+
{
12+
}

Provider/Api/Filter/Length.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Provider\Api\Filter;
4+
5+
class Length
6+
{
7+
/**
8+
* @var int
9+
*/
10+
protected $max;
11+
12+
/**
13+
* @param array $options
14+
*/
15+
public function __construct($options = [])
16+
{
17+
$max = empty($options['max']) ? 255 : $options['max'];
18+
$this->max = (int)$max;
19+
}
20+
21+
/**
22+
* Check and truncate string if required
23+
*
24+
* @param string $str
25+
*
26+
* @return string
27+
*/
28+
public function __invoke($str = '')
29+
{
30+
if (empty($str)) {
31+
return $str;
32+
}
33+
34+
$length = mb_strlen($str);
35+
36+
if ($length > $this->max) {
37+
// every part of string is important so no '...' in the end
38+
$str = trim($str);
39+
$str = mb_substr($str, 0, $this->max);
40+
}
41+
42+
return $str;
43+
}
44+
}

Provider/ApiClient.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace SymfonyRollbarBundle\Provider;
4+
5+
use Symfony\Component\DependencyInjection\ContainerInterface;
6+
use SymfonyRollbarBundle\DependencyInjection\SymfonyRollbarExtension;
7+
8+
/**
9+
* Class ApiClient
10+
*
11+
* @package SymfonyRollbarBundle\Provider
12+
*/
13+
class ApiClient
14+
{
15+
const API_VERSION = '1';
16+
17+
/**
18+
* @var \Symfony\Component\DependencyInjection\ContainerInterface
19+
*/
20+
protected $container;
21+
22+
/**
23+
* @var string
24+
*/
25+
protected $endpoint;
26+
27+
/**
28+
* @var \GuzzleHttp\Client
29+
*/
30+
protected $client;
31+
32+
/**
33+
* ApiClient constructor.
34+
*
35+
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
36+
*/
37+
public function __construct(ContainerInterface $container)
38+
{
39+
$this->container = $container;
40+
41+
// There is no API in Rollbar SDK for tracking builds
42+
$config = $this->container->getParameter(SymfonyRollbarExtension::ALIAS . '.config');
43+
$this->endpoint = $config['rollbar']['base_api_url'];
44+
45+
$this->client = new \GuzzleHttp\Client([
46+
'base_uri' => $this->endpoint,
47+
]);
48+
}
49+
50+
/**
51+
* @TODO: inject mocked clienty
52+
*
53+
* @param array $payload
54+
*
55+
* @link https://rollbar.com/docs/api/deploys/
56+
*/
57+
public function trackBuild($payload = [])
58+
{
59+
$this->client->post('deploy', [
60+
'form_params' => $payload,
61+
]);
62+
}
63+
}

Provider/RollbarHandler.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
use Monolog\Logger;
77
use Rollbar\Rollbar as RollbarNotifier;
88
use Symfony\Component\DependencyInjection\ContainerInterface;
9+
use Symfony\Component\HttpFoundation\Request;
910
use SymfonyRollbarBundle\DependencyInjection\SymfonyRollbarExtension;
1011
use Rollbar\Payload\Level;
12+
use SymfonyRollbarBundle\Provider\Api\Filter;
1113

1214
class RollbarHandler extends AbstractProcessingHandler
1315
{
@@ -160,4 +162,41 @@ public function close()
160162
{
161163
$this->flush();
162164
}
165+
166+
/**
167+
* Track new build with Rollbar
168+
*
169+
* @param string $environment
170+
* @param string $revision
171+
* @param string $comment
172+
* @param string $rollbarUser
173+
* @param string $localUser
174+
*
175+
* @return bool
176+
*/
177+
public function trackBuild($environment, $revision, $comment = '', $rollbarUser = '', $localUser = '')
178+
{
179+
// There is no API in Rollbar SDK for tracking builds
180+
$config = $this->getContainer()->getParameter(SymfonyRollbarExtension::ALIAS . '.config');
181+
182+
if (!$config['enable']) {
183+
return false;
184+
}
185+
186+
/** @var \SymfonyRollbarBundle\Provider\ApiClient $client */
187+
$client = $this->getContainer()->get('symfony_rollbar.provider.api_client');
188+
189+
// truncate payload according to limits
190+
$payload = [
191+
'access_token' => $config['rollbar']['access_token'],
192+
'environment' => Filter::process($environment, Filter\Length::class),
193+
'revision' => Filter::process($revision, Filter\Length::class),
194+
// @link https://stackoverflow.com/questions/4420164/how-much-utf-8-text-fits-in-a-mysql-text-field
195+
'comment' => Filter::process($comment, Filter\Length::class, ['max' => 21800]),
196+
'rollbar_username' => Filter::process($rollbarUser, Filter\Length::class),
197+
'local_username' => Filter::process($localUser, Filter\Length::class),
198+
];
199+
200+
return $client->trackBuild($payload);
201+
}
163202
}

Resources/config/services.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ parameters:
22
symfony_rollbar.event_listener.exception_listener.class: SymfonyRollbarBundle\EventListener\ExceptionListener
33
symfony_rollbar.event_listener.error_listener.class: SymfonyRollbarBundle\EventListener\ErrorListener
44
symfony_rollbar.provider.rollbar_handler.class: SymfonyRollbarBundle\Provider\RollbarHandler
5+
symfony_rollbar.provider.api_client.class: SymfonyRollbarBundle\Provider\ApiClient
6+
symfony_rollbar.command.deploy.class: SymfonyRollbarBundle\Command\DeployCommand
57

68
services:
79
symfony_rollbar.event_listener.exception_listener:
@@ -16,8 +18,19 @@ services:
1618
tags:
1719
- { name: kernel.event_listener, event: kernel.exception }
1820

21+
symfony_rollbar.provider.api_client:
22+
class: "%symfony_rollbar.provider.api_client.class%"
23+
public: true
24+
lazy: true
25+
arguments: ["@service_container"]
26+
1927
symfony_rollbar.provider.rollbar_handler:
2028
public: true
2129
lazy: true
2230
class: "%symfony_rollbar.provider.rollbar_handler.class%"
2331
arguments: ["@service_container"]
32+
33+
symfony_rollbar.command.deploy:
34+
class: "%symfony_rollbar.command.deploy.class%"
35+
tags:
36+
- {name: console.command, command: "rollbar:deploy"}

0 commit comments

Comments
 (0)