Every developer deals with the same tasks on daily basis. For instance working with git, linting yaml files, build and releasing modules, calling http APIs and so on.
So, welcome Tomtit - a task and workflow
manager built on Sparrow engine that allows one to easily develop harness scripts and run them though a high-level Raku scenarios.
If you're terminal and automation lover - welcome to this post, I'll show how the use of Tomtit could increase your productivity tremendously.
Install Tomtit
Tomtit is a Raku module - so it's installed through a Raku package manager:
$ zef install --/test Tomtit
Setup
Once Tomtit is installed one can use tom
- command line api to make an initial setup:
$ tom --completion
$ source ~/.tom_completion.sh
$ s6 --repo-init ~/repo
Once commands are executed you'll setup a local Sparrow repository (in case you want to use plugins, see further) and install bash completion for a tom client.
In our post we're going to use an example Raku project to show typical Tomtit workflow:
$ git clone https://github.com/melezhik/rakudist-teddy-bear.git
Before we get started we need to initialize our project with some technical directory required by Tomtit:
$ cd rakudist-teddy-bear
$ tom --init
Create some tasks
Now, let's give it a run and create some script that automate our work.
Consider a simple example from Raku world of testing and building of Raku source code:
$ tom --edit build-app
/home/ubuntu/projects/rakudist-teddy-bear/.tom/build-app.pl6 does not exit, do you want to create it? (type Y to confirm): Y
Once we confirm a creation of new scenario tom will run editor defined at $EDITOR
so we can create a raku script:
#!raku
task-run ".tom/tasks/build";
So far it just a function task-run
that is exported by Tomtit, and that run a script located at .tom/tasks/build
folder, now we need to implement the underlying script:
$ mkdir -p .tom/tasks/build
$ nano .tom/tasks/build/task.bash
!#bash
prove6 --lib t/
zef install --force-install .
As we one can see we choose here Bash for an underlying script, as it fits best for this simple tasks. One could also choose between other languages, that are supported by Sparrow - underlying Tomtit engine.
Now we can run a build application task by using a tom command line:
$ tom build-app
17:05:12 10/04/2020 [repository] index updated from index updated from file:///home/ubuntu/repo/api/v1/index
17:05:13 10/04/2020 [.tom/tasks/build] t/00-load.t .. ok
17:05:13 10/04/2020 [.tom/tasks/build] All tests successful.
17:05:13 10/04/2020 [.tom/tasks/build] Files=1, Tests=1, 0 wallclock secs
17:05:13 10/04/2020 [.tom/tasks/build] Result: PASS
17:05:17 10/04/2020 [.tom/tasks/build] ===> Installing: Teddy Bear:ver<0.0.1>
To edit a task, run:
$ tom --edit build-app
And you'll get your $EDITOR
opening task source code ...
More examples
Tomtit allow more then that. We've just seen a simple example.
Let me bring some more ones.
Creating a task that return a value back to Raku scenario
Say one have a http endpoint (it could be any internal API) that return some output in JSON format to be proceeded. These type of tasks are quite frequent in my daily $job. It's dead easy to create a Tomtit helper for that:
$ mkdir -p .tom/tasks/trigger-api/tasks/http-call
$ nano .tom/tasks/trigger-api/tasks/http-call/task.bash
#!bash
curl -f -o $cache_root_dir/out.json $(config url)
$ nano .tom/tasks/trigger-api/hook.pl6
#!raku
run_task "http-call";
$ nano .tom/tasks/trigger-api/task.pl6
#!raku
use JSON::Tiny;
update_state from-json("{cache_root_dir()}/out.json".IO.slurp)
$ tom --edit trigger-api
#!raku
my %state = task-run ".tom/tasks/trigger-api", %(
url => "http://foo.bar.baz/API"
);
say "data received", %state.perl;
And run the task as:
$ tom trigger-api
Sharing your tasks with others
Very soon, as I develop my scripts I see that some of them repeatable and solve the same tasks. To reduce code duplication and allow team members to use my scripts I can package them and distribute as Sparrow plugins. Remember that Tomtit built on the top of Sparrow?
So for the last example I can move a trigger-api
script into separate git repository and convert in into a plugin:
$ mkdir ~/plugins/
$ mv .tom/tasks/trigger-api/ ~/plugins
$ cd ~/plugins/trigger-api
$ nano sparrow.json
{
"name" : "trigger-api",
"description" : "call http API",
"version" : "0.0.1"
}
And finally upload it to a repository:
$ s6 --upload
02:31:46 10/05/2020 [repository] upload plugin
02:31:46 10/05/2020 [repository] upload trigger-api@0.0.1
Once a plugin uploaded to repository you can make it public by just running a web server with document root at repository root:
$ cd ~/repo && python -m http.server 8000
So my team would pick it up as:
$ export SP6_REPO=http://$my_host:8000
Now the last bit - let's refactor trigger-api
Raku task so that it uses a plugin:
#!raku
my %state = task-run "http call", "trigger-api", %(
url => "http://foo.bar.baz/API"
);
say "data received", %state.perl;
That is it. I hope you've enjoyed the post. As usual I'd appreciate any feedback and comments.