Skip to content

Commit 4ed9879

Browse files
committed
Add support for public runtimes hosted in github
1 parent 9744c42 commit 4ed9879

File tree

3 files changed

+96
-25
lines changed

3 files changed

+96
-25
lines changed

.gitignore

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
*
2-
!/src/*
3-
!.editorconfig
4-
!.gitattributes
5-
!.gitignore
6-
!composer.json
7-
!devstack
8-
!LICENSE
9-
!README.md
1+
composer.lock
2+
.DS_Store
3+
vendor
4+
example

src/Commands/InitStack.php

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Webteractive\Devstack\RuntimeDownloader;
66
use Webteractive\Devstack\File;
7+
use Webteractive\Devstack\PublicRuntimeDownloader;
78
use Webteractive\Devstack\ShouldConfigure;
89

910
class InitStack extends Base
@@ -18,10 +19,23 @@ class InitStack extends Base
1819

1920
public function handle(): int
2021
{
22+
$destination = $this->option('dest', getcwd());
23+
2124
$this->ensureConfigurationIsSet(
2225
$runtime = $this->argument('runtime')
2326
);
2427

28+
if (filter_var($runtime, FILTER_VALIDATE_URL)) {
29+
$resolvedRuntime = (new PublicRuntimeDownloader)->download($runtime);
30+
if ((new File)->copyDirectory($this->devstackStorage()->path($resolvedRuntime), $destination)) {
31+
$this->info($this->makeMessage($runtime, $destination));
32+
} else {
33+
$this->error("Failed to load the {$runtime} runtime to {$destination}, copy of runtime was unsuccessful.");
34+
}
35+
36+
return static::SUCCESS;
37+
}
38+
2539
$this->resolveRuntimes();
2640

2741
if (is_null($runtime)) {
@@ -31,25 +45,11 @@ public function handle(): int
3145
);
3246
}
3347

34-
$destination = $this->option('dest', getcwd());
48+
3549

3650
if ($resolvedRuntime = ($this->runtimes[$runtime] ?? null)) {
3751
if ((new File)->copyDirectory($this->devstackStorage()->path($resolvedRuntime), $destination)) {
38-
$this->info("
39-
Runtime for <comment>{$runtime}</comment> is now loaded to {$destination}.
40-
41-
You can now run the <comment>dev</comment> command. To get started, run <comment>dev up</comment> or <comment>dev up -d</comment> to start the docker containers.
42-
For the first run, it will build the images first and proceed running the containers. To stop the
43-
containers, run <comment>dev down</comment>. For more details on the avaialble commands, run <comment>dev help</comment>.
44-
45-
To exclude the runtime files to your repository, add the following files below to your .gitignore file:
46-
47-
<fg=white>/docker</>
48-
<fg=white>dev</>
49-
<fg=white>docker-compose.yml</>
50-
51-
You're now all set, happy trails!
52-
");
52+
$this->info($this->makeMessage($runtime, $destination));
5353
} else {
5454
$this->error("Failed to load the {$runtime} runtime to {$destination}, copy of runtime was unsuccessful.");
5555
}
@@ -88,4 +88,22 @@ public function getAvailableRuntimes()
8888
return collect($this->devstackStorage()->directories('runtimes'))
8989
->map(fn ($item) => pathinfo($item, PATHINFO_BASENAME));
9090
}
91+
92+
public function makeMessage($runtime, $destination)
93+
{
94+
return "
95+
Runtime for <comment>{$runtime}</comment> is now loaded to {$destination}.
96+
97+
You can now run the <comment>dev</comment> command. To get started, run <comment>dev up</comment> or <comment>dev up -d</comment> to start the docker containers.
98+
For the first run, it will build the images first and proceed running the containers. To stop the
99+
containers, run <comment>dev down</comment>. For more details on the avaialble commands, run <comment>dev help</comment>.
100+
101+
To exclude the runtime files to your repository, add the following files below to your .gitignore file:
102+
103+
<fg=white>/docker</>
104+
<fg=white>dev</>
105+
<fg=white>docker-compose.yml</>
106+
107+
You're now all set, happy trails!";
108+
}
91109
}

src/PublicRuntimeDownloader.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Webteractive\Devstack;
4+
5+
use ZipArchive;
6+
use Illuminate\Support\Str;
7+
8+
class PublicRuntimeDownloader
9+
{
10+
use WithStorage,
11+
WithHttp;
12+
13+
public function download($url)
14+
{
15+
$archive = $this->homePath('runtimes.zip');
16+
$finalDownloadUrl = $this->resolveDownloadUrl($url);
17+
$response = $this->http()->get($finalDownloadUrl, [
18+
'sink' => $archive
19+
]);
20+
21+
if ($response->getStatusCode() == 200) {
22+
if (($zip = new ZipArchive)->open($archive)) {
23+
$zip->extractTo($this->homePath('tmp'));
24+
$zip->close();
25+
$this->devstackStorage()->delete('runtimes.zip');
26+
$extracted = $this->devstackStorage()->directories('tmp')[0];
27+
$newRuntimeName = sha1($finalDownloadUrl);
28+
if ($this->devstackStorage()->exists('runtimes/' . $newRuntimeName)) {
29+
$this->devstackStorage()->deleteDirectory('runtimes/' . $newRuntimeName);
30+
}
31+
$this->devstackStorage()->move($extracted, 'runtimes/' . $newRuntimeName);
32+
$this->devstackStorage()->deleteDirectory('tmp');
33+
return join('/', ['runtimes', $newRuntimeName]);
34+
}
35+
}
36+
37+
return false;
38+
}
39+
40+
public function isFromGithub($url)
41+
{
42+
return Str::contains($url, 'github.com');
43+
}
44+
45+
public function resolveDownloadUrl($url)
46+
{
47+
if ($this->isFromGithub($url)) {
48+
$downloadUrl = Str::of($url)
49+
->replace('https://github.com', 'https://api.github.com/repos')
50+
->append('/releases/latest')
51+
->toString();
52+
$response = $this->http()->get($downloadUrl);
53+
return json_decode($response->getBody(), true)['zipball_url'];
54+
}
55+
56+
return $url;
57+
}
58+
}

0 commit comments

Comments
 (0)