Project: agent

Build now

Configuration

sparrowdo:
  no_sudo: true
  no_index_update: false
  bootstrap: false
  format: default
  repo: https://sparrowhub.io/repo
disabled: false
keep_builds: 100
allow_manual_run: true

Job

#!raku

use Sparky::JobApi;

use Random::Names;

class Pipeline

does Sparky::JobApi::Role

{

  method base-dir {
    "{%*ENV<HOME>}/.brownie"
  }
  
  method stage-main {

    my $random-int = (0..9).flat.roll(8).join("");

    directory self.base-dir unless self.base-dir.IO ~~ :d;

    my $agent-id = "{self.base-dir}/agent-id".IO ~~ :f 
    ?? "{self.base-dir}/agent-id".IO.slurp 
    !! $random-int;

    unless  "{self.base-dir}/agent-id".IO ~~ :f {
      "{self.base-dir}/agent-id".IO.spurt($random-int);
    }

    my $agent = ( %*ENV<BRW_AGENT_NAME_PREFIX> || Random::Names.new.docker-name ) ~ "-" ~ $agent-id;

    say "agent: $agent";

    bash "raku -V > rakuenv.txt";

    my $my = Sparky::JobApi.new( :mine );

    $my.put-file("rakuenv.txt","rakuenv.txt");

    file-delete "tasks.tar";

    say "archiving tasks/ to tasks.tar";

    bash "tar cf {$*CWD}/tasks.tar -C tasks/ .";    

    my $orch-job = Sparky::JobApi.new(
      :api(config()<orchestrator-url>),
      :project<browny.queue>,
      :job-id($agent),
    );

    my $orch-job2 = Sparky::JobApi.new(
      :api(config()<orchestrator-url>),
      :project("{$agent}.ping"),
    );


    my $i = 1;

    while True {

      if ($i == 1) {
        # register agent / send agent heartbeat 
        # every 60 seconds
        $orch-job2.queue({
          description => "heartbit from $agent", 
          tags => %(
            agent => $agent,
            stage => "ping",
          ),
        });
         $i++;
      } elsif ($i == 6) {
         $i = 1;
      } else {
         $i++;
      }
      sleep(10);

      my $q = $orch-job.get-stash();

      say "load requests from orchestrator queue";
      
      if $q {
        my $version = $q<version>;
        if "{self.base-dir}/jobs/{$q<run-id>}".IO ~~ :d {
            say "skip job: {$q<run-id>}, already in agent queue";
        } else {
          say "///";
          say "run tests for job: {$q<run-id>}";
          say "///";
          my $j = Sparky::JobApi.new(
            :project<agent.job>,
          );
          $j.put-stash(%(list => $q<modules><>));
          $j.put-file("tasks.tar","tasks.tar");
          my %tags = %(
              rakudo-version => $version,
              stage => "test",
              agent => $agent,
              zef_test_degree => %*ENV<ZEF_FETCH_DEGREE>,
              zef_fetch_degree => %*ENV<ZEF_TEST_DEGREE>,
          );
          %tags<zef_install_to> = True if %*ENV<ZEF_INSTALL_TO>;
          $j.queue({
            description => "job: {$q<run-id>}", 
            tags => %tags,
          });
          directory "{self.base-dir}/jobs/{$q<run-id>}";
        }
      }
      say "<<< sleep for 10 seconds";

    }
  }

  method stage-test {

    my $my = Sparky::JobApi.new( :mine );

    bash "raku -V > rakuenv.txt";

    $my.put-file("rakuenv.txt","rakuenv.txt");

    my $blob = $my.get-file("tasks.tar");

    directory "tasks";

    my $fh = open "tasks/tasks.tar", :w, :bin;
    $fh.write($blob);
    $fh.close;

    bash "tar -xf tasks.tar  && ls -l", %(
      cwd => "{$*CWD}/tasks",
      description => "unpack tasks.tar",
    );

    my @list = $my.get-stash()<list><>;

    say ">>>";

    say "list: \n", @list.join("\n");

    say "<<<";


    my %results;

    my $orch-job = Sparky::JobApi.new(
      :api(config()<orchestrator-url>),
      :project<agent.report>,
    );

    "list.txt".IO.spurt(@list.join("\n"));

    $my.put-file("list.txt","list.txt");

    my $status = True;

    for @list -> $m {
      %results{$m} = %( status => "", log => "" );
      my $s = task-run "tasks/run-test", %(
        module => $m,
        zef_install_to => tags()<zef_install_to>,
        zef_test_degree => tags()<zef_test_degree>,
        zef_fetch_degree => tags()<zef_fetch_degree>,
      );
      if $s<success> == 1 {
        %results{$m}<status> = True
      } else {
        %results{$m}<status> = False;
        $status = False;
      }
      if "log.txt".IO ~~ :e {
        %results{$m}<log> = "log.txt".IO.slurp;
        $my.put-file("log.txt","{$m}.log.txt");
      }
    }

    $orch-job.put-stash(%results);

    $orch-job.queue({
      description => "results from {tags()<agent>}", 
      tags => %(
        version => tags()<rakudo-version>,
        stage => "results",
      ),
    });

    say "results:";
    say "<<<";
    for %results.kv -> $k, $v {
        say "$k ... {$v<status>}\t "
    }  
    say ">>>";
    die "some tests failed" unless $status;

  }

  method stage-ping {

    directory "{self.base-dir}/agents";
    
    "{self.base-dir}/agents/{tags()<agent>}".IO.unlink;

    "{self.base-dir}/agents/{tags()<agent>}".IO.spurt("");

  }

  method stage-results {

    my $me = Sparky::JobApi.new( :mine );

    my $resutls = $me.get-stash();
    my $version = tags()<version>;
    my @list;
    my $status = True;
    for $resutls.kv -> $k, $v {
      directory "{self.base-dir}/versions/$version/$k";
      if $v<status> {
        "{self.base-dir}/versions/$version/{$k}.OK".IO.spurt("");
        push @list, "$k ... \t OK";
        if $v<log> {
          say "log:";
          say ">>>";
          say $v<log>;
        }
      } else {
        "{self.base-dir}/versions/$version/{$k}.FAIL".IO.spurt("");
        push @list, "$k ... \t FAIL";
        $status = False;
        if $v<log> {
          say "log:";
          say ">>>";
          say $v<log>;
          "{self.base-dir}/versions/$version/{$k}.log".IO.spurt($v<log>);
          $me.put-file("{self.base-dir}/versions/$version/{$k}.log","{$k}.log");
        }
      }

    }

    "summary.txt".IO.spurt(@list.join("\n"));
    $me.put-file("summary.txt","summary.txt");

    say ">>>";
    die "some tests failed" unless $status;

  }
}


Pipeline.new.run;