DEV Community

Cover image for Development workflow management using Tomtit
Alexey Melezhik
Alexey Melezhik

Posted on

Development workflow management using Tomtit

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
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Before we get started we need to initialize our project with some technical directory required by Tomtit:

$ cd rakudist-teddy-bear
$ tom --init
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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";
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
!#bash
prove6 --lib t/
zef install --force-install .
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

To edit a task, run:

$ tom --edit build-app
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
#!bash
curl -f -o $cache_root_dir/out.json  $(config url)
Enter fullscreen mode Exit fullscreen mode
$ nano .tom/tasks/trigger-api/hook.pl6
Enter fullscreen mode Exit fullscreen mode
#!raku
run_task "http-call"; 
Enter fullscreen mode Exit fullscreen mode
$ nano .tom/tasks/trigger-api/task.pl6
Enter fullscreen mode Exit fullscreen mode
#!raku
use JSON::Tiny;
update_state from-json("{cache_root_dir()}/out.json".IO.slurp) 
Enter fullscreen mode Exit fullscreen mode
$ tom --edit trigger-api
Enter fullscreen mode Exit fullscreen mode
#!raku
my %state = task-run ".tom/tasks/trigger-api", %(
   url => "http://foo.bar.baz/API"
);

say "data received", %state.perl;
Enter fullscreen mode Exit fullscreen mode

And run the task as:

$ tom trigger-api
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
{
  "name" : "trigger-api",
  "description" : "call http API",
  "version" : "0.0.1"
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

So my team would pick it up as:

$ export SP6_REPO=http://$my_host:8000 
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

That is it. I hope you've enjoyed the post. As usual I'd appreciate any feedback and comments.

Discussion (0)