loading...

Portable Profiles with Tomtit

melezhik profile image Alexey Melezhik ・4 min read

tomtit logo


One of the nice features of Tomtit is that users can create scripts using Sparrowdo DSL and then package those one as regular Perl6 modules.

Let me show how to do this.

Tomtit profile

Tomtit profile is set of predefined scripts, say, I want to automate some routine operations that come from one my project to another. Instead of copy/paste git/clone them why not define those ones as Perl6 module and reuse it?!

Well, let me introduce Tomtit profiles.

Profile is Perl6 module

Say we have 3 simple operations we repeat again and again over all our projects:

  • Dog - to say something as dogs do
  • Cat - to say something as cats do
  • Fish - to ( not ) to say something as fishes do

Consider creating Tomtit profile containing all 3 scripts representing our operations:

Tomtit::Profile::Pets:

#!perl6

use v6;

unit module Tomtit::Profile::Pets:ver<0.0.1>;

our sub profile-data () {

  my %a is Map  = (
    cat   => (slurp %?RESOURCES<cat.pl6>.Str),
    dog   => (slurp %?RESOURCES<dog.pl6>.Str),
    fish  => (slurp %?RESOURCES<fish.pl6>.Str)
  );

}  

Every animal's scripts is just a Perl6 module resource:

resources/
  cat.pl6
  dog.pl6
  fish.pl6

Sparrowdo DSL and Extensions

We are free Sparrowdo DSL when writing Tomtit scripts, for example:

cat.pl6:

#!perl6


group "cats";

user "cat", %( group => 'cats' );

package-install "cats";

bash "echo 'cats say miu miu'";

Usually Sparrowdo DSL is enough to write your scripts, it has a lot of battery included definitions. But you can always extend DSL by writing specific sparrow plugin and call it through task-run method:

cat.pl6:

#!perl6

task-run "feed my cat", "cat-feed", %(
    food  => "Friskies",
    drink => "Water"
);

Placeholders and Configurations

As I said those scripts are meant for use across various projects. However there are might be parts of a script which are common for all the projects and vise versa are specific to every project. The easiest way to handle this commonality/uniqueness problem is to add placeholders instead of actual values which are project specific:

cat.pl6:

#!perl6


# This should be cat's group and it's specific to every project
# Change it appropriately 
# Once you install the script

my $group = "ChangeMe";

group $group;

user "cat", %( group => $group );

Or you can even use Tomtit environments data to populate project specific data inside your scripts, this is even more maintainable:

cat.pl6:

#!perl6


# This should be cat's group and it's specific to every project
# Change it appropriately 
# Once you install the script

my $group = config<cats><group>;

group $group;

user "cat", %( group => $group );

To create Tomtit environment configuration say this:

tom --env-edit default

#!perl6

{
   cats => %(
       group => "bobtail"     
   ) 
}

Anyway once the script is installed you either modify it in place filling placeholders or set environment data, so everything works properly.

Let's go ahead and see how we distribute our scripts through Tomtit profiles.

Using profile by Tomtit

Once our Tomtit::Profile::Pets profile is ready we can start using it through Tomtit:

zef install Tomtit::Profile::Pets

We add profile to configuration file so it could be seen through Bash completion:

~/tom.yaml


profiles:

  - Tomtit-Profile-Pets

Now let's install profile:

tom --profile <TAB><TAB>

ado                           hello                         perl6                         Tomtit-Profile-Pets
git                           perl                          ruby


tom --profile Tomtit-Profile-Pets

install Tomtit::Profile::Pets@cat ...
install Tomtit::Profile::Pets@dog ...
install Tomtit::Profile::Pets@fish ...

The cool thing about profiles is the way I can share my scripts with others. They single point of knowledge is just tomtit cli configuration files including all the necessary profile references with underneath are just Per6l modules. So having this configuration file in repository and installing related Perl6 modules is all is required to bring my scripts to others:

~/tom.yaml :

profiles:

  Tomtit-Profile-Pets
  Tomtit-Profile-Birds
  Tomtit-Profile-Humans

Install profile modules:

zef install Tomtit::Profile::Pets Tomtit::Birds Tomtit-Humans

Install profile scripts:

tom --profile Tomtit-Profile-Birds # so on

The installed scripts are useful on project initialization stage when you need to copy existed harness logic into your new project. However those scripts are not considered "static", one day I can update existed profile to add more scripts or fix bug in old ones, the end users will only have to updated related Perl6 module and reinstall script from profile:


zef upgrade Tomtit::Profile::Pets
tom --profile Tomtit-Profile-Pets

You can even take it more granular way, updating/installing only specific script:

tom --profile Tomtit-Profile-Pets@fish

To list available scripts within profile just say:

tom --list --profile $profile:

tom --list --profile Tomtit-Profile-Pets

load portable profile Tomtit::Profile::Pets as Perl6 module ...
[profile scenarios]
Tomtit::Profile::Pets@cat       installed: False
Tomtit::Profile::Pets@dog       installed: False
Tomtit::Profile::Pets@fish      installed: False

Conclusion

Tomtit profile is good way to distribute scripts across projects, they are easy to maintainable, easy to write and rely on powerful and simle Sparrowdo DSL and could be extended by plugin written on other languages.

Why not give it a try?


Thank you for reading.

Posted on by:

melezhik profile

Alexey Melezhik

@melezhik

Sparrow6 - Raku Automation Framework

Discussion

markdown guide