2023-11-23 18:02:40 +00:00
|
|
|
# bootstrap
|
2023-11-22 21:39:27 +00:00
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
CLI utility for defining custom project initialization scripts.
|
|
|
|
|
2023-11-25 15:55:02 +00:00
|
|
|
TODO:
|
2023-11-25 18:51:42 +00:00
|
|
|
- [ ] Add evaluator tests.
|
|
|
|
- [ ] Color output to console.
|
2023-11-25 22:25:01 +00:00
|
|
|
- [ ] string -> line, case insensitive
|
|
|
|
- [ ] Ensure keys are alphanumeric, underscore
|
|
|
|
- [ ] sophie
|
2023-11-25 15:55:02 +00:00
|
|
|
|
2023-11-22 21:55:55 +00:00
|
|
|
## Overview
|
2023-11-22 21:39:27 +00:00
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
`bootstrap` is a tool for quickly defining your own init-like scripts. If you
|
|
|
|
are familiar with tools like
|
|
|
|
|
|
|
|
* `npm init`
|
|
|
|
* `nix flake init`
|
|
|
|
* `django-admin startproject`
|
|
|
|
* `mix phx.new`
|
|
|
|
* etc.
|
2023-11-22 21:39:27 +00:00
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
this project will feel at home. Ultimately the goal is to create (optionally)
|
|
|
|
interactive scripts like those mentioned in the above list to quickly scaffold
|
|
|
|
your new projects in a consistent way.
|
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
---
|
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
We start with an example. Consider the following *spec*, which we'll name
|
2023-11-25 22:25:01 +00:00
|
|
|
`touch` (this example exists as a [pre-packaged spec](./specs/touch)):
|
2023-11-25 19:43:41 +00:00
|
|
|
```json
|
2023-11-22 21:39:27 +00:00
|
|
|
{
|
2023-11-25 19:43:41 +00:00
|
|
|
"filename": {
|
2023-11-25 22:25:01 +00:00
|
|
|
"type": "text",
|
2023-11-25 19:48:21 +00:00
|
|
|
"prompt": "What file should I create for you? "
|
2023-11-25 19:43:41 +00:00
|
|
|
}
|
2023-11-22 21:39:27 +00:00
|
|
|
}
|
|
|
|
```
|
2023-11-25 22:25:01 +00:00
|
|
|
and its associated *runner*:
|
2023-11-25 19:43:41 +00:00
|
|
|
```bash
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
echo "Creating $FILENAME"
|
|
|
|
touch "$OUT/$FILENAME"
|
|
|
|
```
|
|
|
|
|
|
|
|
Running `bootstrap` with these two files configured will invoke the following
|
|
|
|
interactive script:
|
|
|
|
```bash
|
2023-11-25 22:25:01 +00:00
|
|
|
$> bootstrap touch
|
|
|
|
What file should I create for you? hello-world.txt
|
|
|
|
Creating hello-world.txt
|
|
|
|
$> ls
|
|
|
|
... hello-world.txt ...
|
2023-11-25 19:43:41 +00:00
|
|
|
```
|
2023-11-25 22:25:01 +00:00
|
|
|
You should now see a new `hello-world.txt` file in your current working
|
2023-11-25 19:48:21 +00:00
|
|
|
directory.
|
2023-11-22 21:39:27 +00:00
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
## Usage
|
2023-11-22 21:39:27 +00:00
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
### Installation
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
### Runners
|
2023-11-25 19:43:41 +00:00
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
A spec refers to any directory containing a file named `runner`. The only
|
|
|
|
requirement enforced by `bootstrap` is for this file to be an executable (e.g.
|
|
|
|
`chmod +x`), but typically the `runner` is a shell script:
|
|
|
|
```bash
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
The `runner` is invoked with its current working directory set to that of the
|
|
|
|
directory containing it. For instance, if we have a `runner` script living in
|
|
|
|
directory `~/Documents/specs/example` with contents:
|
|
|
|
```bash
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
echo "$PWD"
|
|
|
|
```
|
|
|
|
the output of `bootstrap example` will *always* be e.g.
|
|
|
|
```bash
|
|
|
|
> bootstrap example
|
|
|
|
/home/jrpotter/Documents/specs/example
|
|
|
|
```
|
|
|
|
regardless of where we call the `bootstrap` command.
|
|
|
|
|
|
|
|
#### Exit Code
|
|
|
|
|
|
|
|
`bootstrap` always invokes the `runner` using the system `sh` command:
|
|
|
|
```bash
|
|
|
|
> /bin/sh sh -c ./runner
|
|
|
|
```
|
|
|
|
The exit code emitted by `bootstrap` will mirror that returned by the `runner`
|
|
|
|
executable.
|
|
|
|
|
|
|
|
### Specs
|
|
|
|
|
|
|
|
If interested in making the `runner` more flexible, you can provide different
|
|
|
|
environment variables in the form of a `spec.json` file. This file must live
|
|
|
|
in the same spec as the `runner`. When invoking `bootstrap`, the file is used to
|
|
|
|
determine what prompts should be displayed to the user before executing the
|
|
|
|
`runner` file. The user's responses are then included as environment variables
|
|
|
|
to the `runner` process.
|
|
|
|
|
|
|
|
The file contents should consist of a top-level JSON object and any number of
|
|
|
|
child objects called *fields*. A typical `spec.json` file looks like:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"fieldname": {
|
|
|
|
"type": "text",
|
|
|
|
"prompt": "Prompt for field> "
|
|
|
|
},
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
In this example, the first field is called `"fieldname"`. `bootstrap` sees this
|
|
|
|
field and writes the prompt `"Prompt for field> "` to `stdout`. Since
|
|
|
|
`"fieldname"` has type `"text"`, `bootstrap` will wait for the user to input
|
|
|
|
a string (submitted with a newline).
|
|
|
|
|
|
|
|
If the user were to enter, say `fieldvalue`, in response to the prompt,
|
|
|
|
the `runner` script would then have access to an environment variable
|
|
|
|
`FIELDNAME` set to `fieldvalue` on launch.
|
|
|
|
|
|
|
|
#### Types
|
|
|
|
|
|
|
|
The value of `type` determines how a field is prompted for. Note the value of
|
|
|
|
`type` is case insenstive. The currently supported list of types are:
|
|
|
|
|
|
|
|
* `text`
|
|
|
|
* The simplest prompt type. Takes in a free-form response submitted after a
|
|
|
|
newline (`\n`) is encountered.
|
|
|
|
|
|
|
|
#### Root Directory
|
|
|
|
|
|
|
|
All specs should exist in the same *root directory*. As an example of what this
|
|
|
|
directory might look like, refer to `specs` at the top-level of this project.
|
|
|
|
When invoking `bootstrap <name>`, `<name>` is expected to correspond to some
|
|
|
|
spec found within the root directory.
|
|
|
|
|
|
|
|
To tell `bootstrap` where your specs are located, you can provide the path to
|
|
|
|
the root directory using the `-d` option like so:
|
|
|
|
```bash
|
|
|
|
> bootstrap -d ~/Documents/specs example
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
If no option is set, `bootstrap` will fallback to using the value of the
|
|
|
|
`BOOTSTRAP_ROOT_DIR` environment variable. If this also isn't set, `bootstrap`
|
|
|
|
will abort with an appropriate error message.
|
2023-11-25 19:43:41 +00:00
|
|
|
|
|
|
|
### Other Environment Variables
|
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
By default, the `runner` command will have the following environment variables
|
|
|
|
defined. Defining these fields in a `spec.json` file will override the default
|
|
|
|
values:
|
2023-11-25 19:43:41 +00:00
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
* `OUT`
|
|
|
|
* The directory `bootstrap` was invoked from. Named since this is usually
|
|
|
|
where you want to initialize new files of your project in.
|
2023-11-25 19:43:41 +00:00
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
### Supplied Specs
|
2023-11-25 19:43:41 +00:00
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
A number of specs are provided out of the box. If you installed `bootstrap`
|
|
|
|
using `nix`, the `BOOTSTRAP_ROOT_DIR` will automatically be set to the location
|
|
|
|
of these [specs](./specs). Keep in mind this list is very opinionated - they
|
|
|
|
reflect my personal needs for projects. Feel free to specify a different specs
|
|
|
|
root directory if these do not fit your needs.
|
2023-11-25 19:43:41 +00:00
|
|
|
|
2023-11-25 22:25:01 +00:00
|
|
|
As a suggestion, use `nix` from within your `runner` scripts for maximum
|
|
|
|
reproducibility. Refer to the provided specs for inspiration on how you can do
|
|
|
|
this.
|
2023-11-23 15:21:50 +00:00
|
|
|
|
|
|
|
## Development
|
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
TODO
|
|
|
|
|
|
|
|
### Documentation
|
|
|
|
|
|
|
|
TODO
|
2023-11-23 15:21:50 +00:00
|
|
|
|
|
|
|
### Formatting
|
|
|
|
|
|
|
|
A `pre-commit` file is included in `.githooks` to ensure consistent formatting.
|
|
|
|
Run the following to configure `git` to use it:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
git config --local core.hooksPath .githooks/
|
|
|
|
```
|
|
|
|
|
2023-11-25 19:43:41 +00:00
|
|
|
If running [direnv](https://direnv.net/), this is done automatically if `git` is
|
|
|
|
installed.
|