Skip to content

Commit 9ab6698

Browse files
committed
Merge branch 'develop'
* develop: specify next release fix test fix test mention in the readme that graphviz needs to be installed decorate commands to check if dot is installed Revert "disable testing against php 8.3"
2 parents 082307b + a07a5de commit 9ab6698

7 files changed

Lines changed: 260 additions & 8 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
matrix:
1010
os: [ubuntu-latest, macOS-latest]
11-
php-version: ['8.2']
11+
php-version: ['8.2', '8.3']
1212
dependencies: ['lowest', 'highest']
1313
name: 'PHPUnit'
1414
steps:
@@ -34,7 +34,7 @@ jobs:
3434
runs-on: ubuntu-latest
3535
strategy:
3636
matrix:
37-
php-version: ['8.2']
37+
php-version: ['8.2', '8.3']
3838
dependencies: ['lowest', 'highest']
3939
name: 'Psalm'
4040
steps:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 3.5.1 - 2023-12-02
4+
5+
### Fixed
6+
7+
- When `dot` is not installed it displays a message telling so instead of crashing
8+
39
## 3.5.0 - 2023-11-26
410

511
### Changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Tool to help visualize the various dependencies between packages.
88

99
It has been created to help maintain the many packages inside this organisation.
1010

11+
> [!NOTE]
12+
> This package needs [graphviz (`dot` command line tool)](https://graphviz.org) to be installed on your machine
13+
1114
## Installation
1215

1316
```sh

src/Command/CheckDotInstalled.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
declare(strict_types = 1);
3+
4+
namespace Innmind\DependencyGraph\Command;
5+
6+
use Innmind\CLI\{
7+
Console,
8+
Command,
9+
};
10+
use Innmind\Server\Control\Server\{
11+
Processes,
12+
Command as Process
13+
};
14+
use Innmind\Immutable\Str;
15+
16+
final class CheckDotInstalled implements Command
17+
{
18+
private Command $command;
19+
private Processes $processes;
20+
21+
public function __construct(Command $command, Processes $processes)
22+
{
23+
$this->command = $command;
24+
$this->processes = $processes;
25+
}
26+
27+
public function __invoke(Console $console): Console
28+
{
29+
/** @psalm-suppress ArgumentTypeCoercion Due to the environment variables */
30+
return $this
31+
->processes
32+
->execute(
33+
Process::foreground('dot')
34+
->withOption('help')
35+
->withEnvironments($console->variables()->filter(
36+
static fn($name) => $name === 'PATH',
37+
)),
38+
)
39+
->wait()
40+
->match(
41+
fn() => ($this->command)($console),
42+
static fn() => $console
43+
->output(Str::of("Graphviz needs to be installed first\n"))
44+
->exit(1),
45+
);
46+
}
47+
48+
/**
49+
* @psalm-mutation-free
50+
*/
51+
public function usage(): string
52+
{
53+
return $this->command->usage();
54+
}
55+
}

src/Kernel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public function __invoke(Application $app): Application
2828
$os->remote()->http(),
2929
$get('package'),
3030
))
31+
->mapCommand(static fn($command, $_, $os) => new Command\CheckDotInstalled(
32+
$command,
33+
$os->control()->processes(),
34+
))
3135
->command(static fn($get, $os) => new Command\FromLock(
3236
new Loader\ComposerLock($os->filesystem()),
3337
$get('save'),
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
<?php
2+
declare(strict_types = 1);
3+
4+
namespace Tests\Innmind\DependencyGraph\Command;
5+
6+
use Innmind\DependencyGraph\Command\CheckDotInstalled;
7+
use Innmind\CLI\{
8+
Console,
9+
Command,
10+
Command\Arguments,
11+
Command\Options,
12+
Environment,
13+
};
14+
use Innmind\Server\Control\Server\{
15+
Processes,
16+
Process,
17+
Process\ExitCode,
18+
Process\Failed,
19+
Process\Output\Output,
20+
};
21+
use Innmind\Immutable\{
22+
Str,
23+
Either,
24+
SideEffect,
25+
Sequence,
26+
};
27+
use PHPUnit\Framework\TestCase;
28+
use Innmind\BlackBox\{
29+
PHPUnit\BlackBox,
30+
Set,
31+
};
32+
33+
class CheckDotInstalledTest extends TestCase
34+
{
35+
use BlackBox;
36+
37+
public function testCallCommandIfInstalled()
38+
{
39+
$this
40+
->forAll(Set\Strings::any())
41+
->then(function($usage) {
42+
$inner = new class($usage) implements Command {
43+
public function __construct(private string $usage)
44+
{
45+
}
46+
47+
public function __invoke(Console $console): Console
48+
{
49+
return $console->output(Str::of('all good'));
50+
}
51+
52+
public function usage(): string
53+
{
54+
return $this->usage;
55+
}
56+
};
57+
$processes = $this->createMock(Processes::class);
58+
$processes
59+
->expects($this->once())
60+
->method('execute')
61+
->with($this->callback(static function($command) {
62+
return $command->toString() === "dot '--help'";
63+
}))
64+
->willReturn($process = $this->createMock(Process::class));
65+
$process
66+
->expects($this->once())
67+
->method('wait')
68+
->willReturn(Either::right(new SideEffect));
69+
$command = new CheckDotInstalled($inner, $processes);
70+
$console = Console::of(
71+
Environment\InMemory::of(
72+
[],
73+
true,
74+
[],
75+
[],
76+
'/',
77+
),
78+
new Arguments,
79+
new Options,
80+
);
81+
82+
$console = $command($console);
83+
84+
$this->assertSame(
85+
['all good'],
86+
$console->environment()->outputs(),
87+
);
88+
});
89+
}
90+
91+
public function testReturnErrorWhenNotInstalled()
92+
{
93+
$this
94+
->forAll(Set\Strings::any())
95+
->then(function($usage) {
96+
$inner = new class($usage) implements Command {
97+
public function __construct(private string $usage)
98+
{
99+
}
100+
101+
public function __invoke(Console $console): Console
102+
{
103+
return $console->output(Str::of('all good'));
104+
}
105+
106+
public function usage(): string
107+
{
108+
return $this->usage;
109+
}
110+
};
111+
$processes = $this->createMock(Processes::class);
112+
$processes
113+
->expects($this->once())
114+
->method('execute')
115+
->with($this->callback(static function($command) {
116+
return $command->toString() === "dot '--help'";
117+
}))
118+
->willReturn($process = $this->createMock(Process::class));
119+
$process
120+
->expects($this->once())
121+
->method('wait')
122+
->willReturn(Either::left(new Failed(
123+
new ExitCode(127),
124+
new Output(Sequence::of()),
125+
)));
126+
$command = new CheckDotInstalled($inner, $processes);
127+
$console = Console::of(
128+
Environment\InMemory::of(
129+
[],
130+
true,
131+
[],
132+
[],
133+
'/',
134+
),
135+
new Arguments,
136+
new Options,
137+
);
138+
139+
$console = $command($console);
140+
141+
$this->assertSame(
142+
1,
143+
$console->environment()->exitCode()->match(
144+
static fn($exit) => $exit->toInt(),
145+
static fn() => null,
146+
),
147+
);
148+
$this->assertSame(
149+
["Graphviz needs to be installed first\n"],
150+
$console->environment()->outputs(),
151+
);
152+
});
153+
}
154+
155+
public function testUsage()
156+
{
157+
$this
158+
->forAll(Set\Strings::any())
159+
->then(function($usage) {
160+
$inner = new class($usage) implements Command {
161+
public function __construct(private string $usage)
162+
{
163+
}
164+
165+
public function __invoke(Console $console): Console
166+
{
167+
return $console;
168+
}
169+
170+
public function usage(): string
171+
{
172+
return $this->usage;
173+
}
174+
};
175+
$processes = $this->createMock(Processes::class);
176+
$command = new CheckDotInstalled($inner, $processes);
177+
178+
$this->assertSame(
179+
$usage,
180+
$command->usage(),
181+
);
182+
});
183+
}
184+
}

tests/Loader/DependenciesTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public function testInvokation()
3838
label="league"
3939
URL="https://packagist.org/packages/league/"
4040
league__uri_parser [label="uri-parser@1.4.1"];
41-
league__uri_interfaces [label="uri-interfaces@7.3.0"];
42-
league__uri [label="uri@7.3.0"];
43-
league__uri_components [label="uri-components@7.3.0"];
41+
league__uri_interfaces [label="uri-interfaces@7.4.0"];
42+
league__uri [label="uri@7.4.0"];
43+
league__uri_components [label="uri-components@7.4.0"];
4444
}
4545
subgraph cluster_psr {
4646
label="psr"
@@ -60,9 +60,9 @@ public function testInvokation()
6060
league__uri_parser [shape="ellipse", width="0.75", height="0.5", color="#bcf2f6", URL="https://packagist.org/packages/league/uri-parser#1.4.1"];
6161
psr__http_message [shape="ellipse", width="0.75", height="0.5", color="#8da3f1", URL="https://packagist.org/packages/psr/http-message#2.0"];
6262
psr__http_factory [shape="ellipse", width="0.75", height="0.5", color="#8ac267", URL="https://packagist.org/packages/psr/http-factory#1.0.2"];
63-
league__uri_interfaces [shape="ellipse", width="0.75", height="0.5", color="#22ca7d", URL="https://packagist.org/packages/league/uri-interfaces#7.3.0"];
64-
league__uri [shape="ellipse", width="0.75", height="0.5", color="#ef36b1", URL="https://packagist.org/packages/league/uri#7.3.0"];
65-
league__uri_components [shape="ellipse", width="0.75", height="0.5", color="#de64b9", URL="https://packagist.org/packages/league/uri-components#7.3.0"];
63+
league__uri_interfaces [shape="ellipse", width="0.75", height="0.5", color="#22ca7d", URL="https://packagist.org/packages/league/uri-interfaces#7.4.0"];
64+
league__uri [shape="ellipse", width="0.75", height="0.5", color="#ef36b1", URL="https://packagist.org/packages/league/uri#7.4.0"];
65+
league__uri_components [shape="ellipse", width="0.75", height="0.5", color="#de64b9", URL="https://packagist.org/packages/league/uri-components#7.4.0"];
6666
innmind__url [shape="ellipse", width="0.75", height="0.5", color="#085cd3", URL="https://packagist.org/packages/innmind/url#4.3.0"];
6767
}
6868
DOT;

0 commit comments

Comments
 (0)