-
-
Notifications
You must be signed in to change notification settings - Fork 364
/
bref
executable file
·123 lines (110 loc) · 4.43 KB
/
bref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env php
<?php
declare(strict_types=1);
use Bref\Console\Deployer;
use GuzzleHttp\Psr7\Stream;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\Process;
const PHP_TARGET_VERSION = '7.2.5';
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
require_once __DIR__ . '/vendor/autoload.php';
} elseif (file_exists(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
} else {
require_once __DIR__ . '/../../autoload.php';
}
$app = new Silly\Application('Deploy serverless PHP applications');
$app->command('init', function (SymfonyStyle $io) {
/*
* TODO We should check that dependencies are correctly installed
* - check that `serverless` is installed
* - check that it is configured with environment variables
* If not, print a link to Bref's documentation and exit with an error.
*/
$fs = new Filesystem;
/*
* TODO Ask for a project name and configure it in `serverless.yml`.
*/
if (!file_exists('serverless.yml')) {
$io->writeln('Creating serverless.yml');
$fs->copy(__DIR__ . '/template/serverless.yml', 'serverless.yml');
}
if (!file_exists('bref.php')) {
$io->writeln('Creating bref.php');
$fs->copy(__DIR__ . '/template/bref.php', 'bref.php');
}
$io->success([
'Project initialized and ready to deploy using `bref deploy`',
'If you are using git, you will need to commit the following files:',
'- bref.php',
'- serverless.yml',
// TODO Do this automatically
'You can add `/.bref/` to your .gitignore.',
]);
});
$app->command(
'local [-f|--function=] [-d|--data=] [-p|--path=] [--raw]',
function (string $function, ?string $data, bool $raw, SymfonyStyle $io) {
$io->write((new Deployer)->invoke($io, $function, $data, $raw));
})
->defaults([
'function' => 'main',
])
->descriptions('Invoke the lambda locally. To pass data to the lambda use the `--data` argument.', [
'--function' => 'The name of the function in your service that you want to invoke. In Bref, by default, there is only the `main` function.',
'--data' => 'String data to be passed as an event to your function. You can provide JSON data here.',
'--raw' => 'Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.',
]);
$app->command('deploy', function (SymfonyStyle $io) {
(new Deployer)->deploy($io);
});
/**
* Run a CLI command in the remote environment.
*/
$app->command('cli [arguments]*', function (array $arguments, SymfonyStyle $io) {
$serverlessInfo = (new Process('serverless info'))->mustRun()->getOutput();
foreach (explode(PHP_EOL, $serverlessInfo) as $line) {
if (strpos($line, 'region: ') === 0) {
$region = substr($line, strlen('region: '));
}
if (strpos($line, 'stack: ') === 0) {
$functionName = substr($line, strlen('stack: ')) . '-main';
}
}
if (empty($region) || empty($functionName)) {
throw new Exception('Unable to parse the output of `serverless info`');
}
// We cannot use the `serverless` CLI command here because it
// mangles the lambda response (JSON data) with logs on stdout.
// Using the AWS SDK allows to collect those data separately and properly.
$lambda = new \Aws\Lambda\LambdaClient([
'version' => 'latest',
'region' => $region,
]);
$result = $lambda->invoke([
'FunctionName' => $functionName,
'LogType' => 'Tail',
'Payload' => json_encode([
'cli' => implode(' ', $arguments),
]),
]);
/** @var Stream $payload */
$payload = $result->get('Payload');
$payload = json_decode($payload->getContents(), true);
if (isset($payload['output'])) {
$io->writeln($payload['output']);
} else {
$io->error('The command did not return a valid response.');
$io->writeln('<info>Logs:</info>');
$io->write('<comment>' . base64_decode($result->get('LogResult')) . '</comment>');
$io->writeln('<info>Lambda result payload:</info>');
$io->writeln(json_encode($payload, JSON_PRETTY_PRINT));
return 1;
}
return (int) ($payload['exitCode'] ?? 1);
});
$app->command('info', function (SymfonyStyle $io) {
$io->write((new Process('serverless info'))->mustRun()->getOutput());
});
$app->run();