Skip to content

Commit 17bc743

Browse files
authored
Merge pull request #12 from christoph-daehne/main
FEATURE: connect to existing Prunner system service
2 parents 43cb72b + ff2d09f commit 17bc743

9 files changed

Lines changed: 179 additions & 20 deletions

File tree

Classes/Composer/InstallerScripts.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ class InstallerScripts
4545

4646
const DEFAULT_VERSION_TO_INSTALL = '1.0.1';
4747

48+
/**
49+
* Downloads the prunner binaries from https://github.com/Flowpack/prunner to ./prunner.
50+
*
51+
* You can pin the prunner version in the composer.json#extra.prunner-version field.
52+
* You can also set it to 'skip-download' to skip the download.
53+
*
54+
* @return void
55+
*/
4856
public static function postUpdateAndInstall()
4957
{
5058
$platform = php_uname('s'); // stuff like Darwin etc
@@ -58,6 +66,10 @@ public static function postUpdateAndInstall()
5866
$version = $extra['prunner-version'];
5967
$versionMessage = ' (OVERRIDDEN in composer.json)';
6068
}
69+
if ($version === 'skip-download') {
70+
echo '> Not downloading prunner (due to "skip-download" instruction in composer.json)';
71+
return;
72+
}
6173

6274
$baseDirectory = 'prunner';
6375
$platformSpecificTargetDirectory = $baseDirectory . '/' . $platform . '_' . $architecture;

Classes/Controller/ProxyController.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ class ProxyController extends \Neos\Flow\Mvc\Controller\ActionController
2222
*/
2323
protected $directory;
2424

25+
/**
26+
* @Flow\InjectConfiguration(path="configFile")
27+
* @var string
28+
*/
29+
protected $configFile;
30+
2531
/**
2632
* @Flow\InjectConfiguration(path="jwtSecret")
2733
* @var string
@@ -56,9 +62,8 @@ public function indexAction(string $path, string $subpath)
5662
} else {
5763
try {
5864
// Try to parse prunner config to get JWT secret
59-
$config = Yaml::parseFile($this->directory . '/.prunner.yml');
60-
$jwtSecret = $config['jwt_secret'];
61-
} catch (ParseException $e) {
65+
$jwtSecret = $this->loadJwtSecretFromConfigFile();
66+
} catch (\RuntimeException $e) {
6267
$this->response->setContentType('application/json');
6368
$this->response->setStatusCode(500);
6469
return json_encode(['error' => 'Invalid prunner configuration (could not read JWT secret)']);
@@ -87,4 +92,26 @@ public function indexAction(string $path, string $subpath)
8792

8893
return $response->getBody();
8994
}
95+
96+
/**
97+
* @return string
98+
*/
99+
private function loadJwtSecretFromConfigFile(): string
100+
{
101+
if ($this->configFile && file_exists($this->configFile)) {
102+
$path = $this->configFile;
103+
} elseif ($this->directory && file_exists($this->directory . '/.prunner.yml')) {
104+
$path = $this->directory . '/.prunner.yml';
105+
} else {
106+
throw new \RuntimeException("Failed to locate prunner config file at " . $this->configFile . " or " . $this->directory . '/.prunner.yml');
107+
}
108+
try {
109+
// Try to parse prunner config to get JWT secret
110+
$config = Yaml::parseFile($path);
111+
$jwtSecret = $config['jwt_secret'];
112+
} catch (ParseException $e) {
113+
throw new \RuntimeException('Invalid prunner configuration (could not read JWT secret)');
114+
}
115+
return $jwtSecret;
116+
}
90117
}

Classes/Dto/Job.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static function fromJsonArray(array $in): self
6363
}
6464

6565
/**
66-
* @return string
66+
* @return JobId
6767
*/
6868
public function getId(): JobId
6969
{

Classes/Dto/Jobs.php

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111
class Jobs implements \IteratorAggregate
1212
{
13+
1314
/**
1415
* @var Job[]
1516
*/
@@ -20,7 +21,6 @@ private function __construct(array $jobs)
2021
$this->jobs = $jobs;
2122
}
2223

23-
2424
public static function fromJsonArray(array $in): self
2525
{
2626
$converted = [];
@@ -42,22 +42,90 @@ public function forPipeline(PipelineName $pipeline): Jobs
4242
return new self($filteredJobs);
4343
}
4444

45+
/**
46+
* @return Jobs all scheduled jobs not yet started
47+
*/
48+
public function waiting(): Jobs
49+
{
50+
return $this->filter(function (Job $job) {
51+
return !$job->getStart();
52+
});
53+
}
54+
4555
/**
4656
* Filter running jobs
4757
*
4858
* @return Jobs
4959
*/
5060
public function running(): Jobs
5161
{
52-
$filteredJobs = [];
53-
foreach ($this->jobs as $job) {
62+
return $this->filter(function (Job $job) {
5463
// running = started jobs which have not finished.
55-
if ($job->getStart() !== null && !$job->getEnd()) {
56-
$filteredJobs[] = $job;
64+
return $job->getStart() !== null && !$job->getEnd();
65+
});
66+
}
67+
68+
/**
69+
* @return Jobs successful, canceled and failed jobs
70+
*/
71+
public function completed(): Jobs
72+
{
73+
return $this->filter(function (Job $job) {
74+
return $job->isCompleted();
75+
});
76+
}
77+
78+
/**
79+
* @return Jobs successfully completed jobs
80+
*/
81+
public function successful(): Jobs
82+
{
83+
return $this->filter(function (Job $job) {
84+
return $job->isCompleted() && !$job->isErrored() && !$job->isCanceled();
85+
});
86+
}
87+
88+
/**
89+
* @return Jobs canceled jobs
90+
*/
91+
public function canceled(): Jobs
92+
{
93+
return $this->filter(function (Job $job) {
94+
return $job->isCanceled();
95+
});
96+
}
97+
98+
/**
99+
* @return Jobs failed jobs
100+
*/
101+
public function errored(): Jobs
102+
{
103+
return $this->filter(function (Job $job) {
104+
return $job->isErrored();
105+
});
106+
}
107+
108+
/**
109+
* @param callable $predicate function(Job $job): bool
110+
* @return Jobs all jobs where $predicate($job)
111+
*/
112+
public function filter(callable $predicate): Jobs
113+
{
114+
$result = [];
115+
foreach ($this->jobs as $job) {
116+
if ($predicate($job)) {
117+
$result[] = $job;
57118
}
58119
}
120+
return new self($result);
121+
}
59122

60-
return new self($filteredJobs);
123+
/**
124+
* @return Job[]
125+
*/
126+
public function getArray(): array
127+
{
128+
return $this->jobs;
61129
}
62130

63131
/**
@@ -67,4 +135,4 @@ public function getIterator()
67135
{
68136
return new \ArrayIterator($this->jobs);
69137
}
70-
}
138+
}

Classes/Dto/Pipelines.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ public static function fromJsonArray(array $in): self
2424
return $pipelines;
2525
}
2626

27+
/**
28+
* @return Pipeline[]
29+
*/
30+
public function getArray(): array
31+
{
32+
return $this->pipelines;
33+
}
2734

2835
/**
2936
* @return \Iterator<Pipeline>
@@ -32,4 +39,4 @@ public function getIterator()
3239
{
3340
return new \ArrayIterator($this->pipelines);
3441
}
35-
}
42+
}

Classes/Dto/TaskResults.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ public function get(string $taskName): ?TaskResult
138138

139139
}
140140

141+
/**
142+
* @return TaskResult[]
143+
*/
144+
public function getArray(): array {
145+
return $this->taskResults;
146+
}
147+
141148
/**
142149
* @return \Iterator<TaskResult>
143150
*/
@@ -156,4 +163,4 @@ public function allowsCallOfMethod($methodName)
156163
return true;
157164
}
158165

159-
}
166+
}

Classes/PrunnerApiService.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class PrunnerApiService
3232
*/
3333
protected $directory;
3434

35+
/**
36+
* @Flow\InjectConfiguration(path="configFile")
37+
* @var string
38+
*/
39+
protected $configFile;
40+
3541
/**
3642
* @Flow\InjectConfiguration(path="jwtSecret")
3743
* @var string
@@ -103,13 +109,7 @@ public function apiCall(string $method, string $subpath, ?string $body): Respons
103109
if (!empty($this->jwtSecret)) {
104110
$jwtSecret = $this->jwtSecret;
105111
} else {
106-
try {
107-
// Try to parse prunner config to get JWT secret
108-
$config = Yaml::parseFile($this->directory . '/.prunner.yml');
109-
$jwtSecret = $config['jwt_secret'];
110-
} catch (ParseException $e) {
111-
throw new \RuntimeException('Invalid prunner configuration (could not read JWT secret)');
112-
}
112+
$jwtSecret = $this->loadJwtSecretFromConfigFile();
113113
}
114114

115115
// There are usecases where we want to call prunner from the CLI. We don't have an initialized user there, thus we
@@ -122,4 +122,25 @@ public function apiCall(string $method, string $subpath, ?string $body): Respons
122122
return $client->request($method, $url, ['headers' => ['Authorization' => 'Bearer ' . $authToken], 'body' => $body, 'http_errors' => false]);
123123
}
124124

125+
/**
126+
* @return string
127+
*/
128+
private function loadJwtSecretFromConfigFile(): string
129+
{
130+
if ($this->configFile && file_exists($this->configFile)) {
131+
$path = $this->configFile;
132+
} elseif ($this->directory && file_exists($this->directory . '/.prunner.yml')) {
133+
$path = $this->directory . '/.prunner.yml';
134+
} else {
135+
throw new \RuntimeException("Failed to locate prunner config file at " . $this->configFile . " or " . $this->directory . '/.prunner.yml');
136+
}
137+
try {
138+
// Try to parse prunner config to get JWT secret
139+
$config = Yaml::parseFile($path);
140+
$jwtSecret = $config['jwt_secret'];
141+
} catch (ParseException $e) {
142+
throw new \RuntimeException('Invalid prunner configuration (could not read JWT secret)');
143+
}
144+
return $jwtSecret;
145+
}
125146
}

Configuration/Settings.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ Flowpack:
33
# Base URL to prunner API
44
apiBaseUrl: 'http://localhost:9009/'
55
# Working directory of prunner for loading config
6+
# DEPRECATED: use configFile
67
directory: '%FLOW_PATH_ROOT%'
8+
# Path to the prunner config file to load the JWT secret for authentication
9+
configFile: '%FLOW_PATH_ROOT%/.prunner.yml'
710
# Explicitly set JWT secret if prunner config is not accessible
811
jwtSecret: ~
912

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ will be downloaded. However, it is possible to override this via `extra.prunner-
4646
}
4747
```
4848

49+
## Skip the Prunner binary download
50+
51+
In case you want to install Prunner manually,
52+
you can skip the download of the Prunner entirely
53+
by setting `extra.prunner-version` in the root `composer.json` to `"skip-download"`.
54+
55+
```json
56+
{
57+
"extra": {
58+
"prunner-version": "skip-download"
59+
}
60+
}
61+
```
62+
4963
## Building the UI package
5064

5165
In [prunner-ui](https://github.com/Flowpack/prunner-ui), run `yarn build`

0 commit comments

Comments
 (0)