Dec 07, 2020 · 6 minutes read

Introducing PloiCLI - a command line interface for ploi.io

Today is release day #1 in 2020. Introducing ploi-cli - a command line interface for managing your sites with ploi.io. In this post I would like to introduce it to you.

Today is release day #1 in 2020. Introducing ploi-cli - a command line interface for managing your sites with ploi.io. In this post I would like to introduce it to you.

When it comes to managing servers or deploying web apps I always choose ploi.io (referral link). It makes deploying and managing servers and sites totally easy and I never had any headaches or sleepless nights because of server problems since using it. But there's one downside for me: every time I update something that needs a .env variable, I have to go the the dashboard, select my server and site and open the env file in my browser to add the new value to the textbox. An if you've ever edited code in a normal text-area you know, there are many nicer things than that.

So recently I've seen that Marcel from Beyond Code has introduced forge-cli, a command line interface for forge provisioned servers and sites, and so I've thought about making one for ploi too.

Lets beginn!

So, I've made a short list, which features the CLI should handle, and came up with basically all the things that I do most, or which are nicer to do in your project directory itself. Currently that's:

  • Creating a new server
  • Linking a site with a server
  • Handling environments
  • Updating the deploy script
  • Deploying
  • SSL Certificates
  • Databases
  • and so one..

I've already worked with laravel-zero once, and it just does what it should do, so it was relativ clear that this is going to be my framework of choice.

So luckily ploi has an API which I can use, and so I've created a Ploi class which handles all the requests which are sent to ploi - not the nicest way, but it works!

Writing commands

The most things are simple API calls, which getting send when performing a command. I've started with a ploi init command, that was the one which I've needed the most. It asks you after the server for the site, creates the site in ploi, auto-detects your git repository url and installs the repository on the remote site on your ploi provisioned server.

Ploi has so called "test-domains" - just a simple subdomain to preview sites even without own domain (https://solitary-lake-oi9jb0oqap.ploi.link/ for example). Wouldn't it be nice, if one of them get enabled for your new site, so that you can take a look if everything got deployed correct? Of course! So, the system will automatically enable one for you and your new project.

Managing environments

As I've said before, managing environment files in your browser isn't that nice, and sometimes I forget to add them to the web interface, when not doing it directly after adding them to my local .env file.

So I've created two environment commands: ploi env:pull and ploi env:push. The pull commands automatically saves the current environment file to your local filesystem, and with the push command, you can easily upload your modified file to ploi. Also it will ask you to delete the local one, that you're always update to date.

So its more easy than ever before to just add your variable to your local .env file, your example file and at the same time to your production file. Without leaving your ide of course.

Deploying

The last point I would like to talk about in this post, is the ploi deploy:run command, which has a nice feature included.

To deploy a site, there are basically two methods: Either via quick deploy, which automatically deploys your site after a push to master, or manually via a button in the dashboard.

I'm not the biggest fan of quick deploy, sometimes I also push to my main branch without wanting to get it deployed directly. So I usually deploy via the second method.

But: starting today, this will have an end as well. The ploi deploy:run command sends a request to ploi to start deploying, and when providing a --log option it will automatically check your server logs. When it has found the latest deployment log, it will automatically output the remote deployment log to your console - that is nice, isn't it?

Small dive into the code

Before ending this post I just want to dive a little into the codebase of the CLI. Lets take a look at DeployCommand.

When running it, it sends an HTTP Request to ploi, to start the deployment process.

1$ploi->deploy($configuration->get('server'), $configuration->get('site'));
2 
3$this->info("✅ Deploying...");

After that, it checks if the --log option is given, if yes it will send a request to the logs endpoint - every second till a log is found, which is created in the last seconds. And if found, it will watch the logs:

1do {
2 $logId = $this->getDeploymentLog($ploi, $configuration);
3 sleep(1);
4} while ($logId == null);
5 
6$this->watchLog($ploi, $configuration, $logId);

Lets take a look at the getDeploymentLog() method:

1private function getDeploymentLog(Ploi $ploi, Configuration $configuration): ?string
2{
3 $logs = $ploi->getLogs($configuration->get('server'), $configuration->get('site'));
4 if (count($logs) == 0) return null;
5 $latestLog = $logs[0];
6 
7 if (!Str::of($latestLog['created_at_human'])->contains('seconds ago')) {
8 return null;
9 }
10 
11 if ((string)(Str::of($latestLog['created_at_human'])->before('seconds ago')) < 5) {
12 return $latestLog['id'];
13 }
14 
15 return null;
16}

So, it will get all the logs, gets the newest one, and checks if the created date contains "seconds ago", if yes it will check if it's created in the last 5 seconds. If that is also true, it will return the log id, otherwise it returns null and the command will run the same method in a second.

When it has found a log id, it will start to watch that given log:

1private function watchLog(Ploi $ploi, Configuration $configuration, string $logId)
2{
3 $printed = "";
4 
5 while (!str_contains($printed, 'Application deployed!')) {
6 $contents = $ploi->getLog($configuration->get('server'), $configuration->get('site'), $logId)['content'];
7 $contents = str_replace($printed, "", $contents);
8 $this->info($contents);
9 $printed .= $contents;
10 sleep(1);
11 }
12}

I've used Application deployed! as keyword to stop watching the logs, so the method checks if this keyword got printed. If yes, the command will end. Otherwise it will replace everything already printed with an empty string to make sure, that everything only gets printed once.

In closing

Using this CLI, deploying with ploi gets even more easy than it is just with ploi itself. There a lot of unmentioned features left, which you can learn about in its documentation.

So that's it for this post, thank you very much for reading and I hope you've liked it! Would love to get some feedback over on twitter or see you on my mailing list. Once in a while I'll write about cool stuff, but no panic: I won't let your inbox overflow.

Have a nice day,

Felix

Did you enjoy what you’ve read?

Once in a while I send an email with some project updates, article drafts or other cool stuff. I won’t share your email and I won’t let your inbox overflow. Promised.