Varying-Vagrant-Vagrants / VVV

An open source Vagrant configuration for developing with WordPress
https://varyingvagrantvagrants.org
MIT License
4.55k stars 849 forks source link

VVV CLI #2504

Open tomjn opened 2 years ago

tomjn commented 2 years ago

vagrant up etc locks us into the vagrant ecosystem, and specifically reinforces the idea that people are using vagrant not VVV. It also means we're missing out on some things

For example:

Wouldn't it be nice to just:

brew install vvv
vvv setup
vvv up

Or if updating VVV was:

vvv selfupdate

Technical notes

bradp commented 2 years ago

I'm totally down for this. I've been doing a bunch of go CLI scripts lately, and I miss when I had the joy of maintaining vv.

Things like configuring a new site are perfect to have a tightly integrated tool, vv was super popular because you just went through prompts to configure a new site, no mucking around with config files.

Also, it gives a good baseline for a GUI to be on top of it, as it can just bundle the binary and call those in the background.

List of potential command ideas:

bradp commented 2 years ago

Quick note on some go packages. I've been using cobra for CLI scripts, along with chalk and they're really nice.

The organization and structure of cobra is super super easy to get into and makes developing new subcommands super fast.

tomjn commented 2 years ago

I did a quick and rough test with urfave/cli with this:

package main

import (
    "fmt"
    "log"
    "os"
    "time"

    "github.com/urfave/cli/v2"
)

func main() {
    app := &cli.App{
        Compiled: time.Now(),
        Version:  "v19.99.0",
        Commands: []*cli.Command{
            {
                Name:    "up",
                Aliases: []string{"start"},
                Usage:   "Start VVV",
                Action: func(c *cli.Context) error {
                    fmt.Println("starting ", c.Args().First())
                    return nil
                },
            },
            {
                Name:    "halt",
                Aliases: []string{"stop"},
                Usage:   "Stop VVV",
                Action: func(c *cli.Context) error {
                    fmt.Println("stopping ", c.Args().First())
                    return nil
                },
            },
            {
                Name:    "destroy",
                Aliases: []string{"stop"},
                Usage:   "Destroy the VVV virtual machine",
                Action: func(c *cli.Context) error {
                    fmt.Println("stopping ", c.Args().First())
                    return nil
                },
            },
            {
                Name:  "status",
                Usage: "The status of the VVV virtual machine",
                Action: func(c *cli.Context) error {
                    fmt.Println("stopping ", c.Args().First())
                    return nil
                },
            },
            {
                Name:  "version",
                Usage: "Reports the VVV version",
                Action: func(c *cli.Context) error {
                    fmt.Println("stopping ", c.Args().First())
                    return nil
                },
            },
            {
                Name:  "sites",
                Usage: "Manages sites",
                Subcommands: []*cli.Command{
                    {
                        Name:  "add",
                        Usage: "add a new site",
                        Action: func(c *cli.Context) error {
                            fmt.Println("new task template: ", c.Args().First())
                            return nil
                        },
                    },
                    {
                        Name:  "list",
                        Usage: "lists sites",
                        Action: func(c *cli.Context) error {
                            fmt.Println("new task template: ", c.Args().First())
                            return nil
                        },
                    },
                    {
                        Name:  "enable",
                        Usage: "enables a disabled site",
                        Action: func(c *cli.Context) error {
                            fmt.Println("removed task template: ", c.Args().First())
                            return nil
                        },
                    },
                    {
                        Name:  "disable",
                        Usage: "disables a site and prevents it from running. This does not delete files or databases.",
                        Action: func(c *cli.Context) error {
                            fmt.Println("removed task template: ", c.Args().First())
                            return nil
                        },
                    },
                },
            },
        },
    }

    err := app.Run(os.Args)
    if err != nil {
        log.Fatal(err)
    }
}

The results were rather nice, good to see a golang equivalent of chalk

tomjn commented 1 year ago

Noting that some contributors expressed concern that golang was unfamiliar, @Mte90 mentioned python as an alternative language that can be packaged up as a self contained binary

I found a few in a quick search:

I'm not an experienced python programmer though I can write it if needed, does anybody have any advice on best practices?

GitHub
GitHub - linkedin/shiv: shiv is a command line utility for building fully self contained Python zipapps as outlined in PEP 441, but with all their dependencies included.
shiv is a command line utility for building fully self contained Python zipapps as outlined in PEP 441, but with all their dependencies included. - GitHub - linkedin/shiv: shiv is a command line ut...
cx_Freeze 6.15.0-dev3 documentation
PyInstaller Manual — PyInstaller 5.10.1 documentation
Nuitka the Python Compiler — Nuitka the Python Compiler documentation
With the Python compiler Nuitka you create protected binaries out of your Python source code.
Mte90 commented 1 year ago

I use it for work pyinstaller, just as note, use the python version available in the system to package the script with all the dependencies in a dedicated binary. So with a CI we can generate a binary for any system with everything.

There is a new similar technology also for php https://github.com/configuredco/haulable that does the same things. It is not the usual phar build but include also the php binary and this one doesn't need to run in every system to generate it as download the various binary and package everything in a single one.

So in any case I think that a script language is better for a wrapper around Vagrant and Docker with integration with /etc/hosts as it is more simple to patch and doesn't require the full binary version. Also simplifies the contribution to everyone as it is something that is used in the WordPress ecosystem if we are looking for contributors.

In my opinion it is just right now to see what we need as command to do a prototype very simple in python or php to see what solution is worth it. In my opinion PHP is better in this way this project doesn't have another language to support, I mean right now we have bash, ruby, nodejs and php.

About best practices looking on internet if uses less possible external dependencies (that have stuff to compile it) is better to avoid issues but it is something that can happen anyway with anything.

GitHub
GitHub - configuredco/haulable: Create standalone PHP CLI applications with PHP Micro CLI
Create standalone PHP CLI applications with PHP Micro CLI - GitHub - configuredco/haulable: Create standalone PHP CLI applications with PHP Micro CLI
tomjn commented 1 year ago

do you know how large the python vs php option would be? If one is 100's kb and the other is 100's mb then that leaves a clear choice. Something to note with python is parallelism is easier

Mte90 commented 1 year ago

Usually python it was like around 30mb I don't know in php, for that I think that we just need to test it.

If I remember I will do it.

tomjn commented 1 year ago

Noting that I did some investigation into this:

I explored PHP and python specifically as @Mte90 expressed concerns about using golang which might be unfamiliar to contributors, and to avoid using NodeJS. However in hindsight golang and Node were the most reliable to set up and get started with

From what I remember, someone in the VVV community has already built a Node JS CLI application for their company that gets daily use. At the time it was offered to us we held off since we wanted to avoid adding an extra depedency with NodeJS, hence exploring golang and python, and avoiding using .phar