DocOps / liquidoc-gem

The canonical gem source for LiquiDoc, a ruby-based documentation parsing and rendering utility enabling advanced builds with Asciidoctor, Jekyll, Liquid, and semi-structured data files.
https://docs.docops.org/liquidoc-user-manual.html
MIT License
12 stars 5 forks source link

Establish 'execute' action for invoking shell commands #64

Closed briandominick closed 5 years ago

briandominick commented 5 years ago

We need a way to execute shell commands and shell scripts from within LiquiDoc. I originally assumed the solution would always be to use a more robust build tool and call LiquiDoc as one of many commands executed. However, now that LD configs are dynamic, it can be far less convenient to break an LD build up, so adding shell power within the operation seems to make sense.

I'm thinking something like this:

action: execute
command: "find _build/ | grep *.adoc > filelist.txt"

This is a little scary, so I am eager to hear any concerns about this, or safeguards. Or additional/complementary settings to add.

diggerlilly commented 5 years ago

I originally assumed the solution would always be to use a more robust build tool and call LiquiDoc as one of many commands executed.

Does this mark a point in the evolution where it does, in fact, make more sense to use a different build tool when doing more complex operations?

briandominick commented 5 years ago

This is the question, for sure. Here is how I see it:

Now that we allow Liquid in the build config file, and thus our config files become dependent on variables passed to them or defined inside them, it's less fair to say to users, "Hey, when you need to run anything we don't already cover with this tool, just fall back to your build tool.

If the required order is such that we build up some useful variables, we must either:

  1. give users the ability to carry values across breaks between config-file executions; or
  2. let users execute commands from within a LiquiDoc config.

Option 1 means LiquiDoc has to produce data for your build tool so your build tool can do something else for a second and then pass data to a new LiquiDoc execution. This feels heavy, but it is also probably very valuable. The more useful, structured data we package as a result of an LD execution, the better. A true API behaves this way.

Option 2 seems like giving the user a magic wand. It's also a baked-in feature of any build tool worth the category. I think this is most useful for aiding in ingesting content/data more flexibly and powerfully. In the example above, we read a file directory and write it to plaintext, so we can immediately ingest that plaintext.

A more complicated implementation would enable direct ingest of command output through STDOUT/STDERR. I imagine that is the evolution of this "action" type. But for now, this enables complex shell commands, and even execution of shell scripts or other CLI utilities.

In conclusion, I think we need all of this eventually, but perhaps the minimum viable solution is to hand off some basic power.

briandominick commented 5 years ago

I am taking a shot at this with PR #65. I think the functionality is just right for an MVP, but I still worry about adding a feature with such power, given that now people can simply issue a hostile config. I've added one precaution, which is an interrogative call and response, forcing you to approve all the commands at once before any of them run, but I don't want to assume this is enough. The only override for this is a --unsafe flag, which I think will warn future practitioners that they had better be careful, if that's the instruction someone provides.

Other than "safety" issues, the biggest limitation of the overall approach is that we can't directly use the results of any command. They would have to be written to file first, then used by a subsequent action. This seems acceptable.