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