feat: expanded on the scripts ideas, added a summary

This commit is contained in:
D. Moonfire 2022-12-20 08:21:14 -06:00
parent b165698a97
commit 875a0daeca

View file

@ -2,7 +2,7 @@
I'm a polyglot programmer. I work in a variety of languages but mostly in [C#](/tags/c-sharp/), [Typescript](/tags/typescript/), and [Rust](/tags/rust/). Every few years, I try a new language to see if I can pick up new ideas or if one "fits" my current mental state better. This is also why I've done a lot dozens of other languages; I would say I know over thirty languages but I'm only a "master" in a handful. I'm a polyglot programmer. I work in a variety of languages but mostly in [C#](/tags/c-sharp/), [Typescript](/tags/typescript/), and [Rust](/tags/rust/). Every few years, I try a new language to see if I can pick up new ideas or if one "fits" my current mental state better. This is also why I've done a lot dozens of other languages; I would say I know over thirty languages but I'm only a "master" in a handful.
I also flit from project to project. I have my [writing](/categories/writing/) and games. I have little one-off programs and ones that I hope will become a major thing. But, like everything else in my life, I'm "gloriously unfocused" on my tasks which means I have to minimize the speed that I get into a project. I also flit from project to project. I have my [writing](/categories/writing/) and games. I have little one-off programs and ones that I hope will become a major thing. But, like everything else in my life, I'm "gloriously unfocused" on my tasks which means I have to minimize the speed that I get into a project before the muse escapes me.
## Tools Selection ## Tools Selection
@ -18,6 +18,8 @@ Though, recent thoughts have suggested that I need to break that "one tool fits
This is where being a polyglot and using different tools comes into play. I have a website that does C#, Typescript, and SASS at the same time. Which one is the "root", which command drives everything? What about a Rust project? Or something else? This is where being a polyglot and using different tools comes into play. I have a website that does C#, Typescript, and SASS at the same time. Which one is the "root", which command drives everything? What about a Rust project? Or something else?
### Shell Scripts
That has kind of led me to my current approach. Instead of always packaging Node in my projects, I really should have a standard location to handle the various actions/targets that apply to any project. Right now, that seems to be shell scripts. That has kind of led me to my current approach. Instead of always packaging Node in my projects, I really should have a standard location to handle the various actions/targets that apply to any project. Right now, that seems to be shell scripts.
With shell scripts, I just have to know that `./scripts/build.sh` will do whatever is needed to build the target. Same with `./scripts/test.sh` and `./scripts/release.sh`. A Rust project may call Cargo, a .NET project will call `dotnet`, and polyglot will call any and all needed to build it. With shell scripts, I just have to know that `./scripts/build.sh` will do whatever is needed to build the target. Same with `./scripts/test.sh` and `./scripts/release.sh`. A Rust project may call Cargo, a .NET project will call `dotnet`, and polyglot will call any and all needed to build it.
@ -27,3 +29,57 @@ This will give me room to experiment. If I decide I want to play with [Cake](/ta
I also went with `.sh` suffixes on the files because while I mostly code in [Linux](/tags/linux/), I also want to support [Powershell](/tags/powershell/) and [Windows](/tags/windows/). That way, it is also clear that `build.sh` and `build.ps1` probably result in the same end-result, but specific for that language. (I know Powershell runs on Linux too.) I also went with `.sh` suffixes on the files because while I mostly code in [Linux](/tags/linux/), I also want to support [Powershell](/tags/powershell/) and [Windows](/tags/windows/). That way, it is also clear that `build.sh` and `build.ps1` probably result in the same end-result, but specific for that language. (I know Powershell runs on Linux too.)
Obviously, some documentation would be required, but that could be a `README.md` file in that directory. That will look nice in [GitLab](/tags/gitlab/) and give documentation. Obviously, some documentation would be required, but that could be a `README.md` file in that directory. That will look nice in [GitLab](/tags/gitlab/) and give documentation.
### Paths
Fortunately, I use [direnv](https://direnv.net/) and [nix-direnv](https://github.com/nix-community/nix-direnv) frequently in my development. This loads the `flake.nix` file as soon as I enter the directory and sets up the tools I need. It also gives me a chance to modify the `PATH` variable but only for that directory which means I can add the `./scripts` folder into the path and have it available anywhere inside the project.
```shell
export PATH=$PWD/scripts:$PATH
use flake || use nix
```
When working with packaging systems such as Node that also include scripts, I also add those into the path. In both cases, `$PWD` is always the directory with the `.envrc` file, even if I change directly into somewhere deeper into the proejct tree; using `$PWD/scripts` means that the `build.sh` command is available anywhere.
```shell
export PATH=$PWD/scripts:$PWD/node-modules/.bin:$PATH
use flake || use nix
```
### Boilerplates
Over the half year or so that I've been using this, I found that I was introducing a few new patterns into my scripts. Mostly these were to support CI/CD environments but also because I like feedback that scripts are doing something.
The most notable aspects were to almost always move into the root directory of the project.
```shell
#! /usr/bin/env bash
cd $(dirname $(dirname $0))
```
In the above case, `$0` is the name of the script. The first `dirname` gets me into the `./scripts` folder, the second gets me into the root. That means that even if I call this script from deep inside the project, the paths are always relative to the project root.
The other is to set up logging so I have something to see what is going on. This is useful for the CI process, but also just so I know something is working properly. I ended up using a consistent start to the scripts to help me identify where the build process was.
```shell
log() { echo "️🧪 $(basename $0): $@"; }
log "running tests/gregorian-tests.scm"
# some testing code
```
When run, it looks like this:
```shell
$ test.sh
🧪 test.sh: running tests/gregorian-tests.scm
......................................
----------------------------------------------------------------------
Ran 38 tests in 0.001s
OK
$
```
Each script usually has their only Unicode character, which also gives the logs a nice colorful appearance and really makes it easier to see where things are going. I ended up using a Bash function for this because it simplifed the calls into a simple `log message` and made it easier to function.
Sadly, Bash doesn't have a good packaging story, so I just copy/paste this into the top of every script along with the `#! /usr/bin/env bash` shebang. Overall, it seems to work and I've been pretty happy with it since.