Portable Profiles with Tomtit
Tags: perl6, linux, workflow, automation
Published: 2019-01-15 16:31:14

---
title: Portable Profiles with Tomtit
published: true
description: Small nifty scripts packaged as Perl6 modules
tags: perl6, linux, workflow, automation
---

![tomtit logo](https://raw.githubusercontent.com/melezhik/tomtit/master/tt-base.png)

---

One of the nice features of [Tomtit](https://github.com/melezhik/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`:

```perl
#!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`:

```perl
#!perl6


group "cats";

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

package-install "cats";

bash "echo 'cats say miu miu'";
```


*Usually* [Sparrowdo DSL](https://github.com/melezhik/sparrowdo/blob/master/core-dsl.md) 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`:

```perl
#!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`:

```perl
#!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](https://github.com/melezhik/tomtit#environments) data to populate project specific data inside your scripts, this is even more maintainable:


`cat.pl6`:

```perl
#!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`


```perl
#!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.