aboutsummaryrefslogtreecommitdiff
path: root/_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2024-02-23 10:35:22 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2024-02-23 10:35:22 +0100
commit4abcce013c9ee3053badf2abda77190233066676 (patch)
tree450de7e8fed3c3c7501a9d2e2eb60a676bdfa09e /_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md
parentcdf50cb2e3051200c6ea0628c318d66220b7d1a1 (diff)
downloadmitjafelicijan.com-4abcce013c9ee3053badf2abda77190233066676.tar.gz
Testing thoughts page
Diffstat (limited to '_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md')
-rw-r--r--_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md160
1 files changed, 160 insertions, 0 deletions
diff --git a/_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md b/_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md
new file mode 100644
index 0000000..c595905
--- /dev/null
+++ b/_posts/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md
@@ -0,0 +1,160 @@
1---
2title: "Re-Inventing Task Runner That I Actually Used Daily"
3permalink: /re-inventing-task-runner-that-i-actually-used-daily.html
4date: 2023-05-31T12:21:10+02:00
5layout: post
6type: post
7draft: false
8---
9
10Couple of months ago I had this brilliant idea of re-inventing the wheel by
11making an alternative for make. And so I went. Boldly into the battle. And to my
12big surprise my attempt resulted in not a completely useless piece of software.
13
14My initial requirements were quite simple but soon grow into something more
15ambitious. And looking back I should have stuck to the simple version. My
16laziness was on my side this time though. Because I haven’t implemented some of
17the features I now realise I really didn’t need them and they would bog the
18whole program and make it be something it was never meant to be.
19
20My basic requirements were following:
21
22- Syntax should be a tiny bit inspired by Rake and Rakefiles.
23- Should borrow the overall feel of a unit test experience.
24- Using something like Python would be a bit of an overkill.
25- The program must be statically compiled, so it can run on same architecture
26 without libc, musl dependencies or things like that.
27- Install ruby for rake is a bit overkill and can not be done with certain
28 really lightweight distributions like Alpine Linux. This tool would be usable
29 on such lightweight systems for remote debugging.
30- I want to use it for more than just compiling things. I want to use it as an
31 entry-point into a project, and I want this to help me indirectly document the
32 project as well.
33- It should be an abstraction over bash shell or the default system shell.
34 - Each task essentially becomes its own shell instance.
35- Must work on Linux and macOS systems.
36- By default, running `erd` list all the available tasks (when I use make, I
37 usually put a disclaimer that you should check Makefile to see all available
38 target).
39- Should support passing arguments when you run it from a shell.
40- Normal variable as the same as environmental variables. There is no
41 distinction. Every variable is also essentially an environment variable and
42 can be used by other programs.
43- State between tasks is not shared, and this makes this “pure” shell instances.
44- Should be single-threaded for the start and later expanded with `@spawn`
45 command.
46- Variables behave like macros and are preprocessed before evaluation.
47- Should support something like `assure` that would check if programs like C
48 compiler or Python (whatever the project requires) are installed on a machine.
49
50Quite a reasonable list of requirements. I do this things already in my
51Makefiles or/and Bash scripts. But I would like to avoid repeating myself every
52time I start working on something new.
53
54So I started with the following syntax.
55
56```ruby
57@env on
58
59# Override the default shell.
60@shell /bin/bash
61
62# Assure that program is installed.
63@assure docker-compose pip python3
64
65# Load local dotenv files (these are then globally available).
66@dotenv .env
67@dotenv .env.sample
68@dotenv some_other_file
69
70# This are local variables but still accessible in tasks.
71@var HI = "hey"
72@var TOKEN = "sometoken"
73@var EMAIL = "m@m.com"
74@var PASSWORD = "pass"
75@var EDITOR = "vim"
76
77@task dev "Test chars .:'}{]!//" does
78 echo "..." $HI
79end
80
81@task clean "Cleans the obj files" does
82 rm .obj
83end
84
85@task greet "Greets the user" does
86 echo "Hi user $TOKEN or $WINDOWID $EMAIL"
87end
88
89@task stack "Starts Docker stack" does
90 docker-compose -f stack.yml up
91end
92
93@task todo "Shows all todos in source files and count them" does
94 grep -ir "TODO|FIXME" . | wc -l
95end
96
97@task test1 "For testing 1" does
98 unknown-command
99 echo "test1"
100 ls -lha
101end
102
103@task test2 "For testing 2" does
104 echo "test1"
105 ls -lha
106 docker-compose -f samples/stack.yml up
107end
108```
109
110One thing that I really like about Errand. Yes, this is what it is called. And
111it is available at https://git.mitjafelicijan.com/errand.git/about/. Moving
112on. One thing that I really like is that a task is a persistent shell. By that I
113mean, that the whole task, even if it contains multiple command in one shell.
114In make each line in a target is that and you need to combine lines or add `\`
115at the end of the line.
116
117```bash
118# How you do this things in make.
119target:
120 source .venv/bin/activate \
121 python script.py
122```
123
124This solves this problem. Consider each task and what is being executed in that
125task a shell that will only close when all the tasks are completed.
126
127By self-documenting I mean that if you are in a directory with `Errandfile` in,
128if you only type `erd` and press enter it should by default display all the
129possible targets. In make i was doing this by having a first target be something
130like `default` that echos the message “Check Makefile for all available target.”
131Because all of the tasks in Errand require a message I use that to display let’s
132call it table of contents.
133
134Because I don’t use any external dependencies this whole thing can be statically
135compiled. So that also checked one of the boxes.
136
137It works on Linux and on a Mac so that’s also a bonus. I don’t believe this
138would work on Windows machines because of the way that I use shell instances. By
139you could use something like Windows Subsystem for Linux and run it in
140there. That is a valid option.
141
142To finish this essay off, how was it to use it in “real life”. I have to be
143honest. Some of the missing features still bother me. `@dotenv` directive is
144still missing and I need to implement this ASAP.
145
146Another thing that needs to happen is support for streaming output. Currently
147commands like `docker-compose` that runs in foreground mode is not compatible
148with Errand. So commands that stream output are an issue. I need to revisit how
149I initiate shell and how I read stdout and stderr. But that shouldn’t be a
150problem.
151
152I have been very satisfied with this thing. I am pleasantly surprised by how
153useful it is. I really wanted to test this in the wild before I commit to it. I
154have more abandoned project than Google and it’s bringing a massive shame to my
155family at this point. So I wanted to be sure that this is even useful. And it
156actually is. Quite surprised at myself.
157
158I really need to package this now and write proper docs. And maybe rewrite
159tokeniser. Its atrocious right now. Site to behold! But that is an issue for
160another time.