Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions recipes/rumvision.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php
/*

### Configuration options

- **api_key** *(required)*: RUMvision API key, used as Bearer token. Each user can create an API key in their RUMvision account.
- **domains** *(required)*: Array of domain names the annotation applies to. When multiple domains are provided, `url_category_ids` must be omitted and `url_scope` must be `all`.
- **title** *(optional)*: Title of the annotation (max 255 characters), defaults to Deployer release name.
- **name_prefix** *(optional)*: A string prefixed to the title.
- **description** *(optional)*: More details about the release.
- **url_scope** *(optional)*: URL scope for the annotation, `all` or `restricted`. Defaults to `all`.
- **url_category_ids** *(optional)*: Array of URL category IDs (UUIDs) scoped to the single provided domain. Required when `url_scope` is `restricted`.
- **impact_at** *(optional)*: Impact timestamp (ISO 8601), defaults to the current time.
- **category_slug** *(optional)*: Annotation category slug, defaults to `hosting`. Available categories: `caching`, `css`, `fonts`, `hosting`, `html`, `images`, `javascript`, `other`, `video`.

```php
// deploy.php

set('rumvision', [
'api_key' => 'k7mbqpzs.Qm8JxL2...',
'domains' => ['example.com'],
]);
```

### Suggested Usage

Since you should only notify RUMvision of a successful deployment, the deploy:rumvision task should be executed right at the end.

```php
// deploy.php

after('deploy', 'deploy:rumvision');
```

*/

namespace Deployer;

use Deployer\Utility\Httpie;

desc('Notifies RUMvision of deployment');
task(
'deploy:rumvision',
static function () {
$defaultConfig = [
'title' => get('release_name'),
'name_prefix' => null,
'description' => null,
'url_scope' => 'all',
'url_category_ids' => null,
'impact_at' => date('c'),
'category_slug' => 'hosting',
'domains' => [],
];

$config = array_merge($defaultConfig, array_filter((array) get('rumvision')));
array_walk(
$config,
static function (&$value) use ($config) {
if (is_callable($value)) {
$value = $value($config);
}
},
);

if (
empty($config['api_key'])
|| empty($config['domains'])
|| !is_array($config['domains'])
) {
throw new \RuntimeException(
<<<EXAMPLE
Required data missing. Please configure rumvision:
set(
'rumvision',
[
'api_key' => 'k7mbqpzs.Qm8JxL2...',
'domains' => ['example.com'],
]
);
EXAMPLE,
);
}

$annotationData = array_filter(
[
'title' => ($config['name_prefix'] ?? '') . $config['title'],
'description' => $config['description'],
'url_scope' => $config['url_scope'],
'url_category_ids' => $config['url_category_ids'],
'impact_at' => $config['impact_at'],
'category_slug' => $config['category_slug'],
'domains' => array_values((array) $config['domains']),
],
static fn($value) => $value !== null && $value !== [],
);

$response = Httpie::post('https://insights.rumvision.com/api/v1/annotations')
->setopt(CURLOPT_TIMEOUT, 10)
->header('Authorization', sprintf('Bearer %s', $config['api_key']))
->jsonBody($annotationData)
->getJson();

if (!isset($response['data']['id'])) {
throw new \RuntimeException(sprintf('Unable to create annotation: %s', print_r($response, true)));
}

writeln(
sprintf(
'<info>RUMvision:</info> Annotation <comment>%s</comment> '
. 'for domain(s): <comment>%s</comment> created successfully.',
$annotationData['title'],
implode(', ', $annotationData['domains']),
),
);
},
);
109 changes: 109 additions & 0 deletions recipes/tideways.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php
/*

### Configuration options

- **api_key** *(required)*: Check to "Project Settings" to find the API key necessary to authenticate the Create Event request.
- **name** *(optional)*: Name of the release, defaults to Deployer release name
- **name_prefix** *(optional)*: a string prefixed to version.
- **type** *(optional)*: Type of the event. Currently supports `release` and `marker`, defaults to `release`.
- **description** *(optional)*: More details about the release.
- **environment** *(optional)*: The environment this release is performed on, otherwise the default environment is used.
- **service** *(optional)*: The service this release is performed on, otherwise the default service of the project is used.
- **compareAfterMinutes** *(optional)*: Defaults to 90 minutes. Specifies the timeframes around the event for which the performance will be compared. Supported values are between 5 minutes and 1440 minutes (one day).

```php
// deploy.php

set('tideways', [
'api_key' => 'Qm8JxL2...'
]);
```

### Suggested Usage

Since you should only notify Tideways of a successful deployment, the deploy:tideways task should be executed right at the end.

```php
// deploy.php

after('deploy', 'deploy:tideways');
```

*/

namespace Deployer;

use Deployer\Utility\Httpie;

desc('Notifies Tideways of deployment');
task(
'deploy:tideways',
static function () {
$defaultConfig = [
'name' => get('release_name'),
'type' => 'release',
'description' => null,
'environment' => null,
'service' => null,
'compareAfterMinutes' => 90,
];

$config = array_merge($defaultConfig, array_filter((array) get('tideways')));
array_walk(
$config,
static function (&$value) use ($config) {
if (is_callable($value)) {
$value = $value($config);
}
},
);

if (
!isset($config['api_key'])
|| empty($config['api_key'])
) {
throw new \RuntimeException(
<<<EXAMPLE
Required data missing. Please configure tideways:
set(
'tideways',
[
'api_key' => 'Qm8JxL2...',
]
);"
EXAMPLE,
);
}

$releaseData = array_filter(
[
'apiKey' => $config['api_key'],
'name' => ($config['name_prefix'] ?? '') . $config['name'],
'description' => $config['description'],
'type' => $config['type'],
'environment' => $config['environment'],
'service' => $config['service'],
'compareAfterMinutes' => $config['compareAfterMinutes'],
],
);

$response = Httpie::post('https://app.tideways.io/api/events')
->setopt(CURLOPT_TIMEOUT, 10)
->jsonBody($releaseData)
->getJson();

if (!isset($response['ok'], $response['id']) || $response['ok'] !== true) {
throw new \RuntimeException(sprintf('Unable to create a release: %s', print_r($response, true)));
}

writeln(
sprintf(
'<info>Tideways:</info> Release of version <comment>%s</comment> '
. 'for project: <comment>%s</comment> created successfully.',
$releaseData['name'],
$response['name'],
),
);
},
);
148 changes: 148 additions & 0 deletions src/AfterDeployTask/Rumvision.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php

namespace Hypernode\DeployConfiguration\AfterDeployTask;

use Hypernode\DeployConfiguration\Configurable\ServerRoleConfigurableInterface;
use Hypernode\DeployConfiguration\Configurable\ServerRoleConfigurableTrait;
use Hypernode\DeployConfiguration\Configurable\StageConfigurableInterface;
use Hypernode\DeployConfiguration\Configurable\StageConfigurableTrait;
use Hypernode\DeployConfiguration\TaskConfigurationInterface;

class Rumvision implements
TaskConfigurationInterface,
ServerRoleConfigurableInterface,
StageConfigurableInterface
{
use ServerRoleConfigurableTrait;

use StageConfigurableTrait;

/**
* @var string
*/
private $apiKey;

/**
* @var string[]
*/
private $domains;

/**
* @var string|null
*/
private $title;

/**
* @var string|null
*/
private $namePrefix;

/**
* @var string|null
*/
private $description;

/**
* @var string|null
*/
private $urlScope;

/**
* @var string[]|null
*/
private $urlCategoryIds;

/**
* @var string|null
*/
private $impactAt;

/**
* @var string|null
*/
private $categorySlug;

/**
* @param string $apiKey RUMvision API key, used as Bearer token
* @param string[] $domains Domain names the annotation applies to
* @param string|null $title Title of the annotation (max 255 characters), defaults to release name
* @param string|null $namePrefix String prefixed to the title
* @param string|null $description More details about the release
* @param string|null $urlScope URL scope for the annotation, `all` or `restricted`
* @param string[]|null $urlCategoryIds URL category IDs (UUIDs), required when $urlScope is `restricted`
* @param string|null $impactAt Impact timestamp (ISO 8601), defaults to the current time
* @param string|null $categorySlug Annotation category slug, defaults to `hosting`
*/
public function __construct(
string $apiKey,
array $domains,
string $title = null,
string $namePrefix = null,
string $description = null,
string $urlScope = null,
array $urlCategoryIds = null,
string $impactAt = null,
string $categorySlug = null
) {
$this->apiKey = $apiKey;
$this->domains = $domains;
$this->title = $title;
$this->namePrefix = $namePrefix;
$this->description = $description;
$this->urlScope = $urlScope;
$this->urlCategoryIds = $urlCategoryIds;
$this->impactAt = $impactAt;
$this->categorySlug = $categorySlug;
}

public function getApiKey(): string
{
return $this->apiKey;
}

/**
* @return string[]
*/
public function getDomains(): array
{
return $this->domains;
}

public function getTitle(): ?string
{
return $this->title;
}

public function getNamePrefix(): ?string
{
return $this->namePrefix;
}

public function getDescription(): ?string
{
return $this->description;
}

public function getUrlScope(): ?string
{
return $this->urlScope;
}

/**
* @return string[]|null
*/
public function getUrlCategoryIds(): ?array
{
return $this->urlCategoryIds;
}

public function getImpactAt(): ?string
{
return $this->impactAt;
}

public function getCategorySlug(): ?string
{
return $this->categorySlug;
}
}
Loading