[Bps-public-commit] RTx-WorkflowBuilder branch, master, updated. 01ac2b7f0976c504f010f2b38c91f25fd84194eb

Kevin Falcone falcone at bestpractical.com
Mon Jan 25 16:43:52 EST 2010


The branch, master has been updated
  discards  01fa0266868ef1c15f2a77eb496970b151d0f78d (commit)
       via  01ac2b7f0976c504f010f2b38c91f25fd84194eb (commit)
       via  98c89c80cadafefb4baede5a8078252290223038 (commit)
       via  a210acabe970eb64f86d72e4c52395040555d794 (commit)
       via  6aba5a491a007f42e2e9e27b0d33d602ff44934c (commit)
       via  d10701554efcbf547ed5cf72817708ab8f6244ae (commit)
       via  30bf063c37bdbc711326c22e78c9bf4460d3b909 (commit)
       via  87d94023cbabc99a75c924dcd1307a85a86271f7 (commit)
       via  097803ced5de526c2e667e82e81a01b52101a98a (commit)
       via  40859fb1efba27d4b04b96fbddf1c3602c1e92ac (commit)
       via  36c41f6b113bfdd4bb5285f709f8ceb0e5a7c0bb (commit)
       via  5b08e709f495282e7df53904d9a175712f37b171 (commit)
       via  162909b53058cf0090392da3f41810f2ef1b2c09 (commit)
       via  1299b473c22440c045a951d5ba8e07c5da904bc0 (commit)
       via  89ebc9188a72c46baf9348dbaf8950ec1e4e4e4d (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (01fa0266868ef1c15f2a77eb496970b151d0f78d)
            \
             N -- N -- N (01ac2b7f0976c504f010f2b38c91f25fd84194eb)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Summary of changes:
 Changes                    |    5 +
 MANIFEST                   |   18 ++++
 Makefile.PL                |   13 +++
 README                     |   51 ++++++++++++
 bin/rt-workflow            |  178 +++++++++++++++++++++++++++++++++++++++++
 lib/RTx/WorkflowBuilder.pm |   99 +++++++++++++++++++++++
 t/basic.t                  |  188 ++++++++++++++++++++++++++++++++++++++++++++
 t/multi-approver.t         |  169 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 721 insertions(+), 0 deletions(-)
 delete mode 100644 .gitignore
 create mode 100644 Changes
 create mode 100644 MANIFEST
 create mode 100644 Makefile.PL
 create mode 100644 README
 create mode 100644 bin/rt-workflow
 create mode 100644 lib/RTx/WorkflowBuilder.pm
 create mode 100644 t/basic.t
 create mode 100644 t/multi-approver.t

- Log -----------------------------------------------------------------
commit 89ebc9188a72c46baf9348dbaf8950ec1e4e4e4d
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Thu Dec 4 13:22:10 2008 +0000

    Directory for svk import.

commit 1299b473c22440c045a951d5ba8e07c5da904bc0
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Thu Dec 4 13:23:08 2008 +0000

    first cut of RTx::WorkflowBuilder

diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644
index 0000000..c8451a7
--- /dev/null
+++ b/Makefile.PL
@@ -0,0 +1,15 @@
+use inc::Module::Install;
+
+RTx('RT-Authen-OpenID');
+
+name            ('RT-Authen-OpenID');
+abstract        ('Allows RT to do authentication via a service which supports the OpenID API');
+author          ('Artur Bergman <sky at crucially.net> and Jesse Vincent <jesse at bestpractical.com>');
+version_from    ('lib/RT/Authen/OpenID.pm');
+license         ('GPL version 2');
+
+requires        ('Net::OpenID::Consumer');
+requires        ('LWPx::ParanoidAgent');
+requires        ('Cache::FileCache');
+
+&WriteAll;
diff --git a/bin/rt-workflow b/bin/rt-workflow
new file mode 100644
index 0000000..f1baf52
--- /dev/null
+++ b/bin/rt-workflow
@@ -0,0 +1,81 @@
+#!/usr/bin/perl -w
+use strict;
+use warnings;
+use Getopt::Long;
+use RTx::WorkflowBuilder;
+
+my ($queue, $wf_name) = @ARGV;
+
+my %opts;
+GetOptions( \%opts, "create" );
+
+use RT::Interface::CLI qw(CleanEnv
+                          GetCurrentUser GetMessageContent);
+CleanEnv();
+
+#Load etc/config.pm and drop privs
+RT::LoadConfig();
+RT::Init();
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Load($queue) or die "Can't load queue: $queue";
+
+my $stages = RT::Config->Get('WorkflowBuilderStages');
+
+my $workflows = RT::Config->Get('WorkflowBuilderRules');
+
+my $scrips = RT::Scrips->new($RT::SystemUser);
+$scrips->Limit( FIELD => 'Queue',
+                VALUE => $q->Id );
+
+my $workflow_script;
+
+die "no workflow named $wf_name found" unless $workflows->{$wf_name};
+
+# XXX: ensure all stages exist
+
+while (my $scrip = $scrips->Next) {
+    # XXX: make sure it's *our* scrip
+    #    next unless .....
+
+    warn $scrip->TemplateObj->Name;
+    if ($workflow_script) {
+        die "two scrips exist for queue @{[ $q->Name ]} workflow: ";
+    }
+    $workflow_script = $scrip;
+}
+
+my $approval_template = RTx::WorkflowBuilder->new
+    ({ stages => $stages,
+       rule   => $workflows->{$wf_name} })
+    ->compile_template;
+
+warn $approval_template;
+
+if (!$workflow_script) {
+    die "no workflow found, use --create" unless $opts{create};
+
+    my $scrip = RT::Scrip->new($RT::SystemUser);
+
+    my $apptemp = RT::Template->new($RT::SystemUser);
+    $apptemp->Create( Content => $approval_template,
+                      Name => $wf_name, Queue => $q->Id);
+
+    my ($sval, $smsg) = $scrip->Create( ScripCondition => 'On Create',
+                                        ScripAction => 'Create Tickets',
+                                        Template => $apptemp->Id,
+                                        Queue => $q->Id);
+}
+else {
+    die "workflow already exists" if $opts{create};
+    warn "updating... $wf_name for @{[ $q->Name ]}";
+
+    warn "template name changed"
+        if $workflow_script->TemplateObj->Name ne $wf_name;
+    $workflow_script->TemplateObj->SetContent($approval_template);
+    $workflow_script->TemplateObj->SetName($wf_name);
+}
+
+
+1;
+
diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
new file mode 100644
index 0000000..3668667
--- /dev/null
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -0,0 +1,73 @@
+package RTx::WorkflowBuilder;
+use base 'Class::Accessor::Fast';
+
+__PACKAGE__->mk_accessors(qw(stages rule));
+
+sub get_stage_object {
+    my ($self, $stage, $previous, $approving) = @_;
+    if (ref $stage eq 'ARRAY') {
+        my @chain = @$stage;
+        for (0..$#chain) {
+            push @result,
+                $self->get_stage_object($chain[$_],
+                                        $_ ? $chain[$_-1] : undef,
+                                        $_ == $#chain ? $approving : undef,
+                                    );
+        }
+        return \@result;
+    }
+    elsif (ref $stage) {
+        die "invalid argument $stage";
+    }
+    else {
+        die "Stage $stage not defined" unless exists $self->stages->{$stage};
+        return RTx::WorkflowBuilder::Stage->new( { name => $stage,
+                                                   depends_on => $previous,
+                                                   depended_on_by => $approving,
+                                                   %{ $self->stages->{$stage} } });
+    }
+}
+
+sub compile_template {
+    my $self = shift;
+    my $stages = $self->get_stage_object($self->rule, undef, 'TOP');
+    return join('', map { $_->compile_template }
+                    map { ref $_ eq 'ARRAY' ? @$_ : $_ } @$stages )."\n"; # flatten with map
+}
+
+package RTx::WorkflowBuilder::Stage;
+use base 'Class::Accessor::Fast';
+
+__PACKAGE__->mk_accessors(qw(name owner content depends_on depended_on_by subject));
+
+sub compile_template {
+    my $self = shift;
+
+    my $attributes = { Queue => '___Approvals',
+                       Type => 'approval',
+                       Owner => $self->owner,
+                       Requestors => '{$Approving->Requestors}',
+                       Subject => $self->subject || 'Approval for ticket {$Approving->Id}: {$Approving->Subject}',
+                       'Refers-To' => 'TOP',
+                       Due => '{time + 86400}', # XXX: configurable
+                       'Content-Type' => 'text/plain',
+                       $self->depends_on ? (
+                           'Depends-On' => "workflow-".$self->depends_on,
+                       ) : (),
+                       $self->depended_on_by ? (
+                           'Depended-On-By' => $self->depended_on_by,
+                       ) : (),
+                   };
+
+    for (values %$attributes) {
+        s/\$Approving/\$Tickets{TOP}/g;
+    }
+
+
+    return join("\n",
+                "===Create-Ticket: workflow-".$self->name,
+                (map { "$_: $attributes->{$_}" } keys %$attributes),
+                "Content: @{[$self->content]}\nENDOFCONTENT\n");
+}
+
+1;
diff --git a/t/basic.t b/t/basic.t
new file mode 100644
index 0000000..26d2028
--- /dev/null
+++ b/t/basic.t
@@ -0,0 +1,196 @@
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN {
+    eval { require Email::Abstract; require Test::Email; 1 }
+        or plan skip_all => 'require Email::Abstract and Test::Email';
+}
+
+plan tests => 38;
+use RT;
+use RT::Test;
+use RT::Test::Email;
+use_ok('RTx::WorkflowBuilder');
+
+RT->Config->Set( LogToScreen => 'debug' );
+
+my ($baseurl, $m) = RT::Test->started_ok;
+
+my ($user_a, $user_b) = (RT::User->new($RT::SystemUser), RT::User->new($RT::SystemUser));
+my ($user_c) = RT::User->new($RT::SystemUser);
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Load('___Approvals');
+
+$q->SetDisabled(0);
+
+my %users;
+for my $user_name (qw(minion jen moss roy cfo ceo )) {
+    my $user = $users{$user_name} = RT::User->new($RT::SystemUser);
+    $user->Create( Name => uc($user_name),
+                   Privileged => 1,
+                   EmailAddress => $user_name.'@company.com');
+    my ($val, $msg);
+    ($val, $msg) = $user->PrincipalObj->GrantRight(Object =>$q, Right => $_)
+        for qw(ModifyTicket OwnTicket ShowTicket);
+
+}
+
+my $stages =
+     { 'Manager approval' => 
+       { content => '.....',
+         subject => 'Manager Approval for PO: {$Approving->Id} - {$Approving->Subject}',
+         owner   => q!{{
+    Fire                => "moss",
+    IT                  => "roy",
+    Marketing           => "jen"}->{ $Approving->FirstCustomFieldValue('Department') }}!,
+     },
+       'Finance approval' =>
+       { content => '... ',
+         owner => 'CFO',
+       },
+       'CEO approval' => 
+       { content => '..........',
+         owner => 'CEO',
+     }};
+
+my $approvals = RTx::WorkflowBuilder->new({ stages => $stages, rule => [ 'Manager approval' => 'Finance approval', 'CEO approval']})->compile_template;
+my $apptemp = RT::Template->new($RT::SystemUser);
+$apptemp->Create( Content => $approvals, Name => "PO Approvals", Queue => "0");
+
+ok($apptemp->Id);
+
+$q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name => 'PO');
+ok ($q->Id, "Created PO queue");
+
+my $dep_cf = RT::CustomField->new( $RT::SystemUser );
+$dep_cf->Create( Name => 'Department', Type => 'SelectSingle', Queue => $q->id );
+$dep_cf->AddValue( Name => $_ ) for qw(IT Marketing Fire);
+
+
+my $scrip = RT::Scrip->new($RT::SystemUser);
+my ($sval, $smsg) =$scrip->Create( ScripCondition => 'On Create',
+                ScripAction => 'Create Tickets',
+                Template => 'PO Approvals',
+                Queue => $q->Id);
+ok ($sval, $smsg);
+ok ($scrip->Id, "Created the scrip");
+ok ($scrip->TemplateObj->Id, "Created the scrip template");
+ok ($scrip->ConditionObj->Id, "Created the scrip condition");
+ok ($scrip->ActionObj->Id, "Created the scrip action");
+
+my $t = RT::Ticket->new($RT::SystemUser);
+my ($tid, $ttrans, $tmsg);
+
+mail_ok {
+    ($tid, $ttrans, $tmsg) =
+        $t->Create(Subject => "answering machines",
+                   Owner => "root", Requestor => 'minion',
+                   'CustomField-'.$dep_cf->id => 'IT',
+                   Queue => $q->Id);
+} { from => qr/PO via RT/,
+    to => 'minion at company.com',
+    subject => qr/answering machines/,
+    body => qr/automatically generated in response/
+};
+
+ok ($tid,$tmsg);
+
+is ($t->ReferredToBy->Count,3, "referred to by the three tickets");
+
+# open the approval tickets that are ready for approval
+mail_ok {
+    for my $ticket ($t->AllDependsOn) {
+        next if $ticket->Type ne 'approval' && $ticket->Status ne 'new';
+        next if $ticket->HasUnresolvedDependencies( Type => 'approval' );
+        $ticket->SetStatus('open');
+    }
+} { from => qr/RT System/,
+    to => 'roy at company.com',
+    subject => qr/New Pending Approval: Manager Approval/,
+    body => qr/pending your approval/
+};
+
+my $deps = $t->DependsOn;
+is ($deps->Count, 1, "The ticket we created depends on one other ticket");
+my $dependson_ceo= $deps->First->TargetObj;
+ok ($dependson_ceo->Id, "It depends on a real ticket");
+like($dependson_ceo->Subject, qr/Approval for ticket.*answering machine/);
+
+$deps = $dependson_ceo->DependsOn;
+is ($deps->Count, 1, "The ticket we created depends on one other ticket");
+my $dependson_cfo = $deps->First->TargetObj;
+ok ($dependson_cfo->Id, "It depends on a real ticket");
+
+$deps = $dependson_cfo->DependsOn;
+is ($deps->Count, 1, "The ticket we created depends on one other ticket");
+my $dependson_roy = $deps->First->TargetObj;
+ok ($dependson_roy->Id, "It depends on a real ticket");
+
+like($dependson_roy->Subject, qr/Manager Approval for PO.*answering machines/);
+
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'new', 'open', 'new', 'new'], 'tickets in correct state');
+
+mail_ok {
+    my $roy = RT::CurrentUser->new;
+    $roy->Load( $users{roy} );
+
+    $dependson_cfo->CurrentUser($roy);
+    my ($ok, $msg) = $dependson_roy->SetStatus( Status => 'resolved' );
+    ok($ok, "roy can approve - $msg");
+
+} { from => qr/RT System/,
+    to => 'cfo at company.com',
+    subject => qr/New Pending Approval/,
+    body => qr/pending your approval/
+},{ from => qr/RT System/, # why is this not roy?
+    to => 'minion at company.com',
+    subject => qr/Ticket Approved:/,
+    body => qr/approved by ROY/
+};
+
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'new', 'resolved', 'open', 'new'], 'tickets in correct state');
+
+# cfo approves
+mail_ok {
+    my $cfo = RT::CurrentUser->new;
+    $cfo->Load( $users{cfo} );
+
+    $dependson_cfo->CurrentUser($cfo);
+    my ($ok, $msg) = $dependson_cfo->SetStatus( Status => 'resolved' );
+    ok($ok, "cfo can approve - $msg");
+
+} { from => qr/RT System/,
+    to => 'ceo at company.com',
+    subject => qr/New Pending Approval/,
+    body => qr/pending your approval/
+},{ from => qr/CFO via RT/,
+    to => 'minion at company.com',
+    subject => qr/Ticket Approved:/,
+    body => qr/approved by CFO/
+};
+
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'new', 'resolved', 'resolved', 'open'], 'tickets in correct state');
+
+# ceo approves
+mail_ok {
+    my $ceo = RT::CurrentUser->new;
+    $ceo->Load( $users{ceo} );
+
+    $dependson_ceo->CurrentUser($ceo);
+    my ($ok, $msg) = $dependson_ceo->SetStatus( Status => 'resolved' );
+    ok($ok, "ceo can approve - $msg");
+
+} { from => qr/CEO via RT/,
+    to => 'minion at company.com',
+    subject => qr/Ticket Approved:/,
+    body => qr/approved by CEO/
+};
+
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'new', 'resolved', 'resolved', 'resolved'], 'tickets in correct state');

commit 162909b53058cf0090392da3f41810f2ef1b2c09
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Thu Dec 4 13:26:34 2008 +0000

    correct makefile.pl

diff --git a/Makefile.PL b/Makefile.PL
index c8451a7..808d8ac 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -1,15 +1,11 @@
 use inc::Module::Install;
 
-RTx('RT-Authen-OpenID');
+RTx('RTx-WorkflowBuilder');
 
-name            ('RT-Authen-OpenID');
-abstract        ('Allows RT to do authentication via a service which supports the OpenID API');
-author          ('Artur Bergman <sky at crucially.net> and Jesse Vincent <jesse at bestpractical.com>');
-version_from    ('lib/RT/Authen/OpenID.pm');
+name            ('RTx-WorkflowBuilder');
+abstract        ('Helpers for building workflow for queues in RT');
+author          ('Chia-liang Kao <clkao at bestpractical.com>');
+version_from    ('lib/RTx//WorkflowBuilder.pm');
 license         ('GPL version 2');
 
-requires        ('Net::OpenID::Consumer');
-requires        ('LWPx::ParanoidAgent');
-requires        ('Cache::FileCache');
-
 &WriteAll;

commit 5b08e709f495282e7df53904d9a175712f37b171
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Fri Dec 5 12:08:43 2008 +0000

    cleanup unused warns.

diff --git a/bin/rt-workflow b/bin/rt-workflow
index f1baf52..6b7ceb4 100644
--- a/bin/rt-workflow
+++ b/bin/rt-workflow
@@ -38,7 +38,6 @@ while (my $scrip = $scrips->Next) {
     # XXX: make sure it's *our* scrip
     #    next unless .....
 
-    warn $scrip->TemplateObj->Name;
     if ($workflow_script) {
         die "two scrips exist for queue @{[ $q->Name ]} workflow: ";
     }
@@ -50,8 +49,6 @@ my $approval_template = RTx::WorkflowBuilder->new
        rule   => $workflows->{$wf_name} })
     ->compile_template;
 
-warn $approval_template;
-
 if (!$workflow_script) {
     die "no workflow found, use --create" unless $opts{create};
 

commit 36c41f6b113bfdd4bb5285f709f8ceb0e5a7c0bb
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Tue Dec 9 15:38:37 2008 +0000

    Thou shall use strict.

diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index 3668667..864a70c 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -1,11 +1,13 @@
 package RTx::WorkflowBuilder;
 use base 'Class::Accessor::Fast';
-
+use strict;
+use warnings;
 __PACKAGE__->mk_accessors(qw(stages rule));
 
 sub get_stage_object {
     my ($self, $stage, $previous, $approving) = @_;
     if (ref $stage eq 'ARRAY') {
+        my @result;
         my @chain = @$stage;
         for (0..$#chain) {
             push @result,
@@ -63,11 +65,12 @@ sub compile_template {
         s/\$Approving/\$Tickets{TOP}/g;
     }
 
+    my $content = $self->content || "\n";
 
     return join("\n",
                 "===Create-Ticket: workflow-".$self->name,
                 (map { "$_: $attributes->{$_}" } keys %$attributes),
-                "Content: @{[$self->content]}\nENDOFCONTENT\n");
+                "Content: $content\nENDOFCONTENT\n");
 }
 
 1;
diff --git a/t/basic.t b/t/basic.t
index 26d2028..2a0a2f6 100644
--- a/t/basic.t
+++ b/t/basic.t
@@ -17,9 +17,6 @@ RT->Config->Set( LogToScreen => 'debug' );
 
 my ($baseurl, $m) = RT::Test->started_ok;
 
-my ($user_a, $user_b) = (RT::User->new($RT::SystemUser), RT::User->new($RT::SystemUser));
-my ($user_c) = RT::User->new($RT::SystemUser);
-
 my $q = RT::Queue->new($RT::SystemUser);
 $q->Load('___Approvals');
 
@@ -168,7 +165,7 @@ mail_ok {
     to => 'ceo at company.com',
     subject => qr/New Pending Approval/,
     body => qr/pending your approval/
-},{ from => qr/CFO via RT/,
+},{ from => qr/RT System/,
     to => 'minion at company.com',
     subject => qr/Ticket Approved:/,
     body => qr/approved by CFO/
@@ -186,7 +183,7 @@ mail_ok {
     my ($ok, $msg) = $dependson_ceo->SetStatus( Status => 'resolved' );
     ok($ok, "ceo can approve - $msg");
 
-} { from => qr/CEO via RT/,
+} { from => qr/RT System/,
     to => 'minion at company.com',
     subject => qr/Ticket Approved:/,
     body => qr/approved by CEO/

commit 40859fb1efba27d4b04b96fbddf1c3602c1e92ac
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Wed Dec 24 11:25:24 2008 +0000

    Allow additional attributes to be bypassed to compile_template.

diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index 864a70c..587f0f3 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -33,7 +33,7 @@ sub get_stage_object {
 sub compile_template {
     my $self = shift;
     my $stages = $self->get_stage_object($self->rule, undef, 'TOP');
-    return join('', map { $_->compile_template }
+    return join('', map { $_->compile_template(@_) }
                     map { ref $_ eq 'ARRAY' ? @$_ : $_ } @$stages )."\n"; # flatten with map
 }
 
@@ -44,7 +44,6 @@ __PACKAGE__->mk_accessors(qw(name owner content depends_on depended_on_by subjec
 
 sub compile_template {
     my $self = shift;
-
     my $attributes = { Queue => '___Approvals',
                        Type => 'approval',
                        Owner => $self->owner,
@@ -53,6 +52,7 @@ sub compile_template {
                        'Refers-To' => 'TOP',
                        Due => '{time + 86400}', # XXX: configurable
                        'Content-Type' => 'text/plain',
+                       @_,
                        $self->depends_on ? (
                            'Depends-On' => "workflow-".$self->depends_on,
                        ) : (),

commit 097803ced5de526c2e667e82e81a01b52101a98a
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Thu Dec 25 07:18:24 2008 +0000

    Filter Owner from Cc, and setup squelch mail.

diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index 587f0f3..002f688 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -61,6 +61,15 @@ sub compile_template {
                        ) : (),
                    };
 
+    if (ref $attributes->{Cc} eq 'ARRAY') {
+        # filter out owner.  Note that at this stage the value can
+        # still be template, so we can not filter the owner if the
+        # template is different but yields same value.
+        $attributes->{Cc} =
+            join(',', grep { $_ ne $self->owner } @{$attributes->{Cc}});
+    }
+    $attributes->{SquelchMailTo} = $attributes->{Cc};
+
     for (values %$attributes) {
         s/\$Approving/\$Tickets{TOP}/g;
     }

commit 87d94023cbabc99a75c924dcd1307a85a86271f7
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Mon Dec 29 19:14:04 2008 +0000

    Bump version

diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..a2014e0
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,15 @@
+bin/rt-workflow
+inc/Module/Install.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install/RTx.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+lib/RTx/WorkflowBuilder.pm
+Makefile.PL
+MANIFEST			This list of files
+META.yml
+t/basic.t
diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index 002f688..bcd6577 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -4,6 +4,8 @@ use strict;
 use warnings;
 __PACKAGE__->mk_accessors(qw(stages rule));
 
+our $VERSION = '1.01';
+
 sub get_stage_object {
     my ($self, $stage, $previous, $approving) = @_;
     if (ref $stage eq 'ARRAY') {

commit 30bf063c37bdbc711326c22e78c9bf4460d3b909
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Tue Jan 6 10:38:37 2009 +0000

    update tests as we now automatically open the leave approval
    and send notification to owner once all approvals are passed.

diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index bcd6577..a0fdb03 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -70,7 +70,8 @@ sub compile_template {
         $attributes->{Cc} =
             join(',', grep { $_ ne $self->owner } @{$attributes->{Cc}});
     }
-    $attributes->{SquelchMailTo} = $attributes->{Cc};
+    $attributes->{SquelchMailTo} = $attributes->{Cc}
+        if $attributes->{Cc};
 
     for (values %$attributes) {
         s/\$Approving/\$Tickets{TOP}/g;
diff --git a/t/basic.t b/t/basic.t
index 2a0a2f6..5fe3dcc 100644
--- a/t/basic.t
+++ b/t/basic.t
@@ -87,29 +87,20 @@ mail_ok {
                    Owner => "root", Requestor => 'minion',
                    'CustomField-'.$dep_cf->id => 'IT',
                    Queue => $q->Id);
-} { from => qr/PO via RT/,
+} { #from => qr/RT/,
+    to => 'roy at company.com',
+    subject => qr/New Pending Approval/,
+    body => qr/pending your approval/,
+},{ from => qr/PO via RT/,
     to => 'minion at company.com',
     subject => qr/answering machines/,
-    body => qr/automatically generated in response/
+    body => qr/automatically generated in response/,
 };
 
 ok ($tid,$tmsg);
 
 is ($t->ReferredToBy->Count,3, "referred to by the three tickets");
 
-# open the approval tickets that are ready for approval
-mail_ok {
-    for my $ticket ($t->AllDependsOn) {
-        next if $ticket->Type ne 'approval' && $ticket->Status ne 'new';
-        next if $ticket->HasUnresolvedDependencies( Type => 'approval' );
-        $ticket->SetStatus('open');
-    }
-} { from => qr/RT System/,
-    to => 'roy at company.com',
-    subject => qr/New Pending Approval: Manager Approval/,
-    body => qr/pending your approval/
-};
-
 my $deps = $t->DependsOn;
 is ($deps->Count, 1, "The ticket we created depends on one other ticket");
 my $dependson_ceo= $deps->First->TargetObj;
@@ -187,6 +178,10 @@ mail_ok {
     to => 'minion at company.com',
     subject => qr/Ticket Approved:/,
     body => qr/approved by CEO/
+},{ from => qr/CEO via RT/,
+    to => 'root at localhost',
+    subject => qr/Ticket Approved:/,
+    body => qr/The ticket has been approved/
 };
 
 is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],

commit d10701554efcbf547ed5cf72817708ab8f6244ae
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Tue Feb 24 08:07:36 2009 +0000

    1.02.

diff --git a/Changes b/Changes
new file mode 100644
index 0000000..cdb2167
--- /dev/null
+++ b/Changes
@@ -0,0 +1,5 @@
+Revision history for RTx-WorkflowBuilder
+
+1.02  Tue Feb 24 16:06:37 CST 2009
+       Initial CPAN release.
+
diff --git a/MANIFEST b/MANIFEST
index a2014e0..96f65b7 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -9,7 +9,9 @@ inc/Module/Install/RTx.pm
 inc/Module/Install/Win32.pm
 inc/Module/Install/WriteAll.pm
 lib/RTx/WorkflowBuilder.pm
+Changes
 Makefile.PL
 MANIFEST			This list of files
 META.yml
+README
 t/basic.t
diff --git a/Makefile.PL b/Makefile.PL
index 808d8ac..7281b34 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -8,4 +8,6 @@ author          ('Chia-liang Kao <clkao at bestpractical.com>');
 version_from    ('lib/RTx//WorkflowBuilder.pm');
 license         ('GPL version 2');
 
+requires        ('Class::Accessor::Fast');
+
 &WriteAll;
diff --git a/README b/README
new file mode 100644
index 0000000..dc72fe7
--- /dev/null
+++ b/README
@@ -0,0 +1,51 @@
+RTx::WorkflowBuilder is a tool for configuring approval workflow in RT.
+
+Best Practical sells support and customization for RT.  Feel free to
+contact us at sales at bestpractical.com if you have any questions about
+our service offerings.
+
+
+Installation instructions:
+--------------------------
+
+1) Install RT 3.8.2 or newer.
+
+2) Once RT appears to be happily installed, cd into the directory
+   where you unpacked RTx::WorkflowBuilder.
+
+3) perl Makefile.PL
+
+4) make install
+
+Further reading:
+-----------------------------------------------------
+
+perldoc bin/rt-workflow - quick overview and configuration
+
+Development
+------------------------------------------------------
+
+If you would like to run RTx::WorkflowBuilder's tests, you need to
+set a few environment variables
+RT_DBA_USER - a user who can create a database on your 
+              RDBMS (such as root on mysql)
+RT_DBA_PASSWORD - the password for RT_DBA_USER
+PERL5LIB - the path to your RT libraries (/opt/rt3/lib)
+
+RT_DBA_USER=user RT_DBA_PASSWORD=password PERL5LIB=/opt/rt3/lib make test
+
+These are intended to be run before installing RTx::WorkflowBuilder.
+Like RT, RTx::WorkflowBuilder expects to be able to create a new
+database called rt3test on your system.
+
+Bug reporting and discussion lists:
+-----------------------------------------------------
+
+You probably want to discuss RTx::WorkflowBuilder on
+rt-users at lists.bestpractical.com.  (Send mail to
+rt-users-request at lists.fsck.com to subscribe)
+
+Bug reports can be sent to bugs-rtx-workflowbuilder at bestpractical.com. 
+You can look at open bug reports at
+https://rt.cpan.org/Public/Dist/Display.html?Name=RTx-WorkflowBuilder.
+Log in as guest/guest to see the content of bug reports.
diff --git a/bin/rt-workflow b/bin/rt-workflow
index 6b7ceb4..a5b90ad 100644
--- a/bin/rt-workflow
+++ b/bin/rt-workflow
@@ -1,13 +1,97 @@
-#!/usr/bin/perl -w
+#!perl -w
 use strict;
 use warnings;
 use Getopt::Long;
 use RTx::WorkflowBuilder;
 
-my ($queue, $wf_name) = @ARGV;
+=head1 NAME
+
+rt-workflow - helper for configuring approval workflow in RT
+
+=head1 SYNOPSIS
+
+In your RT_SiteConfig.pm:
+
+  Set( $WorkflowBuilderStages,
+       { 'Manager approval' =>
+         { content => '.....',
+           subject => 'Manager Approval for PO: {$Approving->Id} - {$Approving->Subject}',
+
+           owner => q!{{
+    Fire                => "moss",
+    IT                  => "roy",
+    Marketing           => "jen"}->{ $Approving->FirstCustomFieldValue('Department') }}! },
+         'Finance approval' =>
+         { content => '... ',
+           owner => 'CFO',
+         },
+         'CEO approval' =>
+         { content => '..........',
+           owner => 'CEO',
+         }});
+
+  Set( $WorkflowBuilderRules,
+  { 'PO-Approval' => [ 'Manager approval' => 'Finance approval' => 'CEO approval'],
+    'Vacation-Approval' => [ 'Manager approval' => 'CEO approval']
+ }
+);
+
+# to enable the workflow rules described in "PO-Approval" for the PO queue:
+% bin/rt-workflow PO PO-Approval --create
+
+# to update the workflow associated with the PO queue once you changed
+# the configuration
+% bin/rt-workflow PO PO-Approval
+
+=head1 DESCRIPTION
+
+This module allows you to define approval stages and approval rules in
+your F<RT_SiteConfig.pm> and builds the appropriate scrips for you.
+
+=over
+
+=item $WorkflowBuilderStages
+
+The config value should be a hashref, with keys being the name of the
+approval stage, and values being a hashref of the approval
+specification, which can include the usual fields for ticket such as
+owner, subject.  note that the values can be interpolated just like
+normal RT Template (escaped with C<{}>), and you can access the ticket to
+be approved with the variable C<$Approving>.
+
+=item $WorkflowBuilderRules
+
+The config value should be a hashref, with keys being the name of the
+approval rule, and the values being arrayref denoting the stages of
+the approval in the suitable order.
+
+A stage with parallel approvals where any of them can move the
+approval workflow to next stage, can be represented as another
+arrayref in the approval chain.  For example:
+
+  ['Manager approval' => 'Financial approval' => 'CEO approval']
+
+implies a monotonous approval chain that goes from manager to
+financial, and finally to CEO.
+
+  ['Manager approval' => ['HR', 'VP'] => 'CEO approval']
+
+implies after manager approval, either one of HR or VP approval will
+make it go to CEO approval.
+
+=back
+
+=cut
 
 my %opts;
-GetOptions( \%opts, "create" );
+GetOptions( \%opts, "create", "help" );
+
+if ($opts{help}) {
+    system("perldoc", $0);
+    exit;
+}
+
+my ($queue, $wf_name) = @ARGV or die "Usage: $0 queue workflowname\n";
 
 use RT::Interface::CLI qw(CleanEnv
                           GetCurrentUser GetMessageContent);
diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index a0fdb03..cf47704 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -4,7 +4,17 @@ use strict;
 use warnings;
 __PACKAGE__->mk_accessors(qw(stages rule));
 
-our $VERSION = '1.01';
+our $VERSION = '1.02';
+
+=head1 NAME
+
+RTx::WorkflowBuilder - helper for configuring approval workflow in RT
+
+=head1 SYNOPSIS
+
+# see rt-workflow
+
+=cut
 
 sub get_stage_object {
     my ($self, $stage, $previous, $approving) = @_;

commit 6aba5a491a007f42e2e9e27b0d33d602ff44934c
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Fri Mar 6 14:32:25 2009 +0000

    Fix workflow template compiling for multi-approver per stage.

diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index cf47704..a7d0712 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -66,7 +66,7 @@ sub compile_template {
                        'Content-Type' => 'text/plain',
                        @_,
                        $self->depends_on ? (
-                           'Depends-On' => "workflow-".$self->depends_on,
+                           'Depends-On' => join(',', map { "workflow-$_" } ref $self->depends_on ? @{ $self->depends_on } : ( $self->depends_on ))
                        ) : (),
                        $self->depended_on_by ? (
                            'Depended-On-By' => $self->depended_on_by,

commit a210acabe970eb64f86d72e4c52395040555d794
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Fri Mar 6 15:56:47 2009 +0000

    add tests for multi-approver for one stage.

diff --git a/t/multi-approver.t b/t/multi-approver.t
new file mode 100644
index 0000000..daa081a
--- /dev/null
+++ b/t/multi-approver.t
@@ -0,0 +1,165 @@
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN {
+    eval { require Email::Abstract; require Test::Email; 1 }
+        or plan skip_all => 'require Email::Abstract and Test::Email';
+}
+
+plan tests => 33;
+use RT;
+use RT::Test;
+use RT::Test::Email;
+use_ok('RTx::WorkflowBuilder');
+
+RT->Config->Set( LogToScreen => 'debug' );
+
+my ($baseurl, $m) = RT::Test->started_ok;
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Load('___Approvals');
+
+$q->SetDisabled(0);
+
+my %users;
+for my $user_name (qw(minion jen moss roy cfo ceo )) {
+    my $user = $users{$user_name} = RT::User->new($RT::SystemUser);
+    $user->Create( Name => uc($user_name),
+                   Privileged => 1,
+                   EmailAddress => $user_name.'@company.com');
+    my ($val, $msg);
+    ($val, $msg) = $user->PrincipalObj->GrantRight(Object =>$q, Right => $_)
+        for qw(ModifyTicket OwnTicket ShowTicket);
+
+}
+
+my $stages =
+     { 'Manager approval' => 
+       { content => '.....',
+         subject => 'Manager Approval for PO: {$Approving->Id} - {$Approving->Subject}',
+         owner   => q!{{
+    Fire                => "moss",
+    IT                  => "roy",
+    Marketing           => "jen"}->{ $Approving->FirstCustomFieldValue('Department') }}!,
+     },
+       'Finance approval' =>
+       { content => '... ',
+         owner => 'CFO',
+         subject => 'CFO approval for PO:  {$Approving->Id} - {$Approving->Subject}',
+       },
+       'CEO approval' => 
+       { content => '..........',
+         owner => 'CEO',
+     }};
+
+my $approvals = RTx::WorkflowBuilder->new({ stages => $stages, rule => [ ['Manager approval', 'Finance approval'], 'CEO approval']})->compile_template;
+warn Dumper($approvals);use Data::Dumper;
+my $apptemp = RT::Template->new($RT::SystemUser);
+$apptemp->Create( Content => $approvals, Name => "PO Approvals", Queue => "0");
+
+ok($apptemp->Id);
+
+$q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name => 'PO');
+ok ($q->Id, "Created PO queue");
+
+my $dep_cf = RT::CustomField->new( $RT::SystemUser );
+$dep_cf->Create( Name => 'Department', Type => 'SelectSingle', Queue => $q->id );
+$dep_cf->AddValue( Name => $_ ) for qw(IT Marketing Fire);
+
+
+my $scrip = RT::Scrip->new($RT::SystemUser);
+my ($sval, $smsg) =$scrip->Create( ScripCondition => 'On Create',
+                ScripAction => 'Create Tickets',
+                Template => 'PO Approvals',
+                Queue => $q->Id);
+ok ($sval, $smsg);
+ok ($scrip->Id, "Created the scrip");
+ok ($scrip->TemplateObj->Id, "Created the scrip template");
+ok ($scrip->ConditionObj->Id, "Created the scrip condition");
+ok ($scrip->ActionObj->Id, "Created the scrip action");
+
+my $t = RT::Ticket->new($RT::SystemUser);
+my ($tid, $ttrans, $tmsg);
+
+mail_ok {
+    ($tid, $ttrans, $tmsg) =
+        $t->Create(Subject => "answering machines",
+                   Owner => "root", Requestor => 'minion',
+                   'CustomField-'.$dep_cf->id => 'IT',
+                   Queue => $q->Id);
+} { #from => qr/RT/,
+    to => 'roy at company.com',
+    subject => qr/New Pending Approval/,
+    body => qr/pending your approval/,
+},{ to => 'cfo at company.com',
+    subject => qr/New Pending Approval/,
+    body => qr/pending your approval/,
+},{ from => qr/PO via RT/,
+    to => 'minion at company.com',
+    subject => qr/answering machines/,
+    body => qr/automatically generated in response/,
+};
+
+ok ($tid,$tmsg);
+
+is ($t->ReferredToBy->Count,3, "referred to by the three tickets");
+
+my $deps = $t->DependsOn;
+is ($deps->Count, 1, "The ticket we created depends on one other ticket");
+my $dependson_ceo= $deps->First->TargetObj;
+ok ($dependson_ceo->Id, "It depends on a real ticket");
+like($dependson_ceo->Subject, qr/Approval for ticket.*answering machine/);
+
+$deps = $dependson_ceo->DependsOn;
+is ($deps->Count, 2, "The ticket we created depends on two other ticket");
+my $dependson_roy = $deps->First->TargetObj;
+ok ($dependson_roy->Id, "It depends on a real ticket");
+like($dependson_roy->Subject, qr/Manager Approval for PO.*answering machines/);
+
+my $dependson_cfo = $deps->Next->TargetObj;
+ok ($dependson_cfo->Id, "It depends on a real ticket");
+like($dependson_cfo->Subject, qr/CFO approval for PO.*answering machines/);
+
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'new', 'open', 'open', 'new'], 'tickets in correct state');
+
+mail_ok {
+    my $roy = RT::CurrentUser->new;
+    $roy->Load( $users{roy} );
+
+    $dependson_roy->CurrentUser($roy);
+    my ($ok, $msg) = $dependson_roy->SetStatus( Status => 'resolved' );
+    ok($ok, "roy can approve - $msg");
+
+} { from => qr/RT System/, # why is this not roy?
+    to => 'minion at company.com',
+    subject => qr/Ticket Approved:/,
+    body => qr/approved by ROY/
+};
+$t->Load($t->id);$dependson_cfo->Load($dependson_cfo->id);
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'open', 'resolved', 'deleted', 'new'], 'tickets in correct state');
+
+# ceo approves
+mail_ok {
+    my $ceo = RT::CurrentUser->new;
+    $ceo->Load( $users{ceo} );
+
+    $dependson_ceo->CurrentUser($ceo);
+    my ($ok, $msg) = $dependson_ceo->SetStatus( Status => 'resolved' );
+    ok($ok, "ceo can approve - $msg");
+
+} { from => qr/RT System/,
+    to => 'minion at company.com',
+    subject => qr/Ticket Approved:/,
+    body => qr/approved by CEO/
+},{ from => qr/CEO via RT/,
+    to => 'root at localhost',
+    subject => qr/Ticket Approved:/,
+    body => qr/The ticket has been approved/
+};
+
+is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
+          [ 'open', 'resolved', 'deleted', 'resolved'], 'tickets in correct state');

commit 98c89c80cadafefb4baede5a8078252290223038
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Fri Mar 6 16:13:52 2009 +0000

    make multi-approver actually work.

diff --git a/MANIFEST b/MANIFEST
index 96f65b7..ae97bd0 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -15,3 +15,4 @@ MANIFEST			This list of files
 META.yml
 README
 t/basic.t
+t/multi-approver.t
diff --git a/lib/RTx/WorkflowBuilder.pm b/lib/RTx/WorkflowBuilder.pm
index a7d0712..eca8473 100644
--- a/lib/RTx/WorkflowBuilder.pm
+++ b/lib/RTx/WorkflowBuilder.pm
@@ -24,7 +24,8 @@ sub get_stage_object {
         for (0..$#chain) {
             push @result,
                 $self->get_stage_object($chain[$_],
-                                        $_ ? $chain[$_-1] : undef,
+                                        $approving eq 'TOP' && $_ != 0
+                                            ? $chain[$_-1] : undef,
                                         $_ == $#chain ? $approving : undef,
                                     );
         }
diff --git a/t/multi-approver.t b/t/multi-approver.t
index daa081a..79bc638 100644
--- a/t/multi-approver.t
+++ b/t/multi-approver.t
@@ -7,7 +7,7 @@ BEGIN {
         or plan skip_all => 'require Email::Abstract and Test::Email';
 }
 
-plan tests => 33;
+plan tests => 34;
 use RT;
 use RT::Test;
 use RT::Test::Email;
@@ -134,13 +134,17 @@ mail_ok {
     ok($ok, "roy can approve - $msg");
 
 } { from => qr/RT System/, # why is this not roy?
+    to => 'ceo at company.com',
+    subject => qr/New Pending/,
+    body => qr/new item pending/
+},{ from => qr/RT System/, # why is this not roy?
     to => 'minion at company.com',
     subject => qr/Ticket Approved:/,
     body => qr/approved by ROY/
 };
 $t->Load($t->id);$dependson_cfo->Load($dependson_cfo->id);
 is_deeply([ map { $_->Status } $t, $dependson_roy, $dependson_cfo, $dependson_ceo ],
-          [ 'open', 'resolved', 'deleted', 'new'], 'tickets in correct state');
+          [ 'open', 'resolved', 'deleted', 'open'], 'tickets in correct state');
 
 # ceo approves
 mail_ok {

commit 01ac2b7f0976c504f010f2b38c91f25fd84194eb
Author: Chia-liang Kao <clkao at bestpractical.com>
Date:   Thu Mar 26 10:32:49 2009 +0000

    - implement --cleanup
    - ignore non-create-tickets scrips when checking workflow scrips.

diff --git a/bin/rt-workflow b/bin/rt-workflow
index a5b90ad..974e81f 100644
--- a/bin/rt-workflow
+++ b/bin/rt-workflow
@@ -43,6 +43,10 @@ In your RT_SiteConfig.pm:
 # the configuration
 % bin/rt-workflow PO PO-Approval
 
+# to cleanup the workflow (all Create Tickets actions) associated with
+# the queue
+% bin/rt-workflow PO --cleanup
+
 =head1 DESCRIPTION
 
 This module allows you to define approval stages and approval rules in
@@ -84,14 +88,18 @@ make it go to CEO approval.
 =cut
 
 my %opts;
-GetOptions( \%opts, "create", "help" );
+GetOptions( \%opts, "create", "cleanup", "help" );
 
 if ($opts{help}) {
     system("perldoc", $0);
     exit;
 }
 
-my ($queue, $wf_name) = @ARGV or die "Usage: $0 queue workflowname\n";
+
+my ($queue, $wf_name) = @ARGV;
+
+die "Usage: $0 queue workflowname\n" unless $queue;
+die "Usage: $0 queue workflowname\n" unless $wf_name || $opts{cleanup};
 
 use RT::Interface::CLI qw(CleanEnv
                           GetCurrentUser GetMessageContent);
@@ -112,6 +120,14 @@ my $scrips = RT::Scrips->new($RT::SystemUser);
 $scrips->Limit( FIELD => 'Queue',
                 VALUE => $q->Id );
 
+if ($opts{cleanup}) {
+    while (my $scrip = $scrips->Next) {
+        next unless $scrip->ScripActionObj->Name eq 'Create Tickets';
+        $scrip->Delete;
+    }
+    exit;
+}
+
 my $workflow_script;
 
 die "no workflow named $wf_name found" unless $workflows->{$wf_name};
@@ -119,11 +135,11 @@ die "no workflow named $wf_name found" unless $workflows->{$wf_name};
 # XXX: ensure all stages exist
 
 while (my $scrip = $scrips->Next) {
-    # XXX: make sure it's *our* scrip
-    #    next unless .....
+    # make sure it's *our* scrip
+    next unless $scrip->ScripActionObj->Name eq 'Create Tickets';
 
     if ($workflow_script) {
-        die "two scrips exist for queue @{[ $q->Name ]} workflow: ";
+        die "two Create Tickets scrips in queue @{[ $q->Name ]} workflow: use --cleanup to remove them\n";
     }
     $workflow_script = $scrip;
 }
@@ -148,10 +164,10 @@ if (!$workflow_script) {
                                         Queue => $q->Id);
 }
 else {
-    die "workflow already exists" if $opts{create};
-    warn "updating... $wf_name for @{[ $q->Name ]}";
+    die "workflow already exists\n" if $opts{create};
+    print "updating... $wf_name for @{[ $q->Name ]}\n";
 
-    warn "template name changed"
+    print "template name changed\n"
         if $workflow_script->TemplateObj->Name ne $wf_name;
     $workflow_script->TemplateObj->SetContent($approval_template);
     $workflow_script->TemplateObj->SetName($wf_name);

-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list