[Bps-public-commit] rt-extension-changemanagement branch master updated. 91a7a4924cfdeab4268739cf12d81affacc33b85

BPS Git Server git at git.bestpractical.com
Fri Feb 11 15:18:26 UTC 2022


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt-extension-changemanagement".

The branch, master has been updated
       via  91a7a4924cfdeab4268739cf12d81affacc33b85 (commit)
       via  cbcb4ca69bbcd70c3506aa59f44873c9dcc39394 (commit)
       via  390ce3e6f9a3b71104020c0f948fd8f81b1bf10f (commit)
       via  af7c1f9f02c2a8d9970563a568fc50e7d54e0eb4 (commit)
       via  7e64be22e802fb8099a8d0e658ebd36dce02cb28 (commit)
       via  5747a20124c3db03bf42429b5e2451e2207369db (commit)
       via  e621f2ce834d310198ac70a97dc576d6738738db (commit)
       via  2a9c5024742d518c1ba6a2ee6f9b42412bbf49c2 (commit)
       via  8da31dec8afbabfdc43637d2ecaaa695e6fed21f (commit)
       via  5fddaad8919e8c2cbbf598467c70facac3795847 (commit)
       via  da0432800f62f484d04951083a8edc1c6df22c11 (commit)
       via  cd01df58cc64a0e1885b0d0724248e2b1d287eb9 (commit)
       via  95081b3d1a6826f982693785ce83362254007af2 (commit)
       via  3f72053b28839de11d6b42f71e710908219c2aef (commit)
      from  c9987f89c80200fc99ec00bad17968cbdb1b96e6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 91a7a4924cfdeab4268739cf12d81affacc33b85
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Fri Feb 11 10:18:15 2022 -0500

    Finish documentation

diff --git a/lib/RT/Extension/ChangeManagement.pm b/lib/RT/Extension/ChangeManagement.pm
index 97e64f4..74d2fc8 100644
--- a/lib/RT/Extension/ChangeManagement.pm
+++ b/lib/RT/Extension/ChangeManagement.pm
@@ -68,18 +68,19 @@ to create tickets in this queue.
 
 =head2 Custom Roles
 
-There are two roles than can be assigned to users that are part of the change 
-management process:
+Users can be assigned several roles that are part of the change management process:
 
 =over
 
 =item Change Reviewer
 
-Someone who can approve a change request
+Person who reviews incoming change requests, and is responsible for approving or
+denying a change request. Can be assigned to a group.
 
 =item Change Implementor
 
-Someone who can implement a change request
+Person who is responsible for implementing a change request. This role can be assigned
+to a group.
 
 =back
 
@@ -191,11 +192,13 @@ changes in the event that the deployment process is unsuccessful.
 Date that the change was started. This is B<not> the same as the normal Started
 date on the ticket - Started is set when the ticket is moved to an open status
 (such as approved); Change Started is when someone actually started implementation 
-of the change.
+of the change. This is set automatically when a change ticket's status changes to
+in progress or partially deployed.
 
 =head3 Change Complete
 
-Date that the change was successfully deployed (or, partially deployed).
+Date that the change was successfully deployed. This is set automatically when a
+change ticket's status changes to deployed.
 
 =head2 Actions
 
@@ -231,18 +234,6 @@ Changes the status of the request to failed. Requires the Change Implementor rol
 
 Cancels the change request (changes status to failed). Requires the Change Implementor role.
 
-=head2 Rights
-
-=head3 Change Reviewer
-
-Person who reviews incoming change requests, and is responsible for approving or
-denying a change request. Can be assigned to a group.
-
-=head3 Change Implementor
-
-Person who is responsible for implementing a change request. This role can be assigned
-to a group.
-
 =head1 CUSTOMIZING AND EXTENDING
 
 There are some ways RT::Extension::ChangeManagement can be customized to provide
@@ -282,12 +273,8 @@ could happen if the change goes awry, etc. Text.
 Using L<RT::Extension::MandatoryOnTransition>, any of the above fields can be made
 required upon a status change. For example, you may wish to make Implementation Steps,
 Validation Steps, and Impact Assessment required fields before a change request can
-be approved.
-
-=head3 Calendar View
-
-With L<RTx::Calendar>, you can add a calendar portlet to your dashboard, as well
-as a full page calendar view of change management tickets and reminders.
+be approved. See F<etc/ChangeManagement_Config.pm> for a ready-to-use example with
+the out of the box configuration.
 
 =head3 Default Values for Custom Fields
 
commit cbcb4ca69bbcd70c3506aa59f44873c9dcc39394
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Fri Feb 11 10:17:28 2022 -0500

    Create example MandatoryOnTransition configuration

diff --git a/etc/ChangeManagement_Config.pm b/etc/ChangeManagement_Config.pm
index 23af68d..7bd5382 100644
--- a/etc/ChangeManagement_Config.pm
+++ b/etc/ChangeManagement_Config.pm
@@ -114,5 +114,28 @@ Set(%Lifecycles,
     }
 );
 
+# Delete the =pod and =cut to activate this configuration. 
+# This example illustrates how to make Change Reviewer, Change Implementor,
+# Change Type, Change Category, and Rollback Plan mandatory for approval
+# of a change management ticket. Make sure to enable MandatoryOnTransition in
+# your primary RT configuration by adding the following:
+# Plugin( "RT::Extension::MandatoryOnTransition" );
+
+=pod
+
+Set( %MandatoryOnTransition,
+    'Change Management' => {
+        'requested -> approved' => [ 
+            'CF.Change Type', 
+            'CF.Change Category', 
+            'CF.Rollback Plan', 
+            'CustomRole.Change Reviewer',
+            'CustomRole.Change Implementor',
+        ],
+    },
+);
+
+=cut
+
 1;
 
commit 390ce3e6f9a3b71104020c0f948fd8f81b1bf10f
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Fri Feb 11 10:16:53 2022 -0500

    Create basic Change Management ACLs

diff --git a/etc/initialdata b/etc/initialdata
index f69534b..b01ab94 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -153,6 +153,37 @@ our @Scrips = (
     },
 );
 
+# These rights aren't the most useful, but it lets everyone, at minimum,
+# submit a ticket.
+my @EveryoneRights = qw/CreateTicket ReplyToTicket SeeQueue/;
+our @ACL = map {
+    {
+        Right       => $_,
+        Queue       => 'Change Management',
+        GroupDomain => 'SystemInternal',
+        GroupType   => 'Everyone'
+    }
+} @EveryoneRights;
+
+# More useful set of rights. Anyone in these groups can see the entirety of 
+# change management tickets, and if a member of one of these groups
+# is assigned to one of the change management roles, they can perform the
+# appropriate actions.
+my @ChangeManagementRights = qw/CommentOnTicket Watch SeeCustomField
+  SeeQueue ShowTicket OwnTicket WatchAsAdminCC StealTicket TakeTicket
+  ShowTicketComments ModifyTicket ModifyCustomField ShowOutgoingEmail
+/;
+foreach my $group( 'Change Management', 'Change Review Team' ) {
+    push @ACL, map {
+        {
+            Right       => $_,
+            Queue       => 'Change Management',
+            GroupDomain => 'UserDefined',
+            GroupId     => $group,
+        }
+    } @ChangeManagementRights;
+}
+
 # 
 # Create some saved searches; these will form the basis of the dashboard below. Add more
 # to suit your organization's needs.
commit af7c1f9f02c2a8d9970563a568fc50e7d54e0eb4
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 10 15:26:32 2022 -0500

    Auto set Change Started/Completed on status change
    
    These dates are important for dashboard reporting and searching, and as
    such, the user shouldn't have to think about setting them. Made a custom
    action to set the date, and use the StatusChange condition to determine
    if they need setting.

diff --git a/etc/initialdata b/etc/initialdata
index 6675f3e..f69534b 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -102,6 +102,57 @@ our @CustomRoles = (
     },
 );
 
+our @ScripConditions = (
+    {
+        Name        => 'On Change Started',
+        Description => 'When an approved change is started',
+        ExecModule  => 'StatusChange',
+        Argument    => 'old: approved; new: in progress, partially deployed',
+        ApplicableTransTypes => 'Any'
+    },
+    {
+        Name        => 'On Change Completed',
+        Description => 'When an approved change is completed',
+        ExecModule  => 'StatusChange',
+        Argument    => 'new: deployed',
+        ApplicableTransTypes => 'Any'
+    },
+);
+
+our @ScripActions = (
+    {
+        Name        => 'Set Change Started to Today',
+        Description => '',
+        ExecModule  => 'SetCustomFieldDate',
+        Argument    => 'Change Started'
+    },
+    {
+        Name        => 'Set Change Completed to Today',
+        Description => '',
+        ExecModule  => 'SetCustomFieldDate',
+        Argument    => 'Change Completed'
+    },
+);
+
+our @Scrips = (
+    {
+        Queue           => ['Change Management'],
+        Description     => 'On Change Started Set Change Started to Today',
+        ScripCondition  => 'On Change Started',
+        ScripAction     => 'Set Change Started to Today',
+        Template        => 'Blank',
+        Stage           => 'TransactionCreate',
+    },
+    {
+        Queue           => ['Change Management'],
+        Description     => 'On Change Completed Set Change Completed to Today',
+        ScripCondition  => 'On Change Completed',
+        ScripAction     => 'Set Change Completed to Today',
+        Template        => 'Blank',
+        Stage           => 'TransactionCreate',
+    },
+);
+
 # 
 # Create some saved searches; these will form the basis of the dashboard below. Add more
 # to suit your organization's needs.
diff --git a/lib/RT/Action/SetCustomFieldDate.pm b/lib/RT/Action/SetCustomFieldDate.pm
new file mode 100644
index 0000000..ff32095
--- /dev/null
+++ b/lib/RT/Action/SetCustomFieldDate.pm
@@ -0,0 +1,32 @@
+package RT::Action::SetCustomFieldDate;
+use base 'RT::Action';
+
+use strict;
+use warnings;
+
+sub Prepare  {
+    # nothing to prepare
+    return 1;
+}
+
+sub Commit {
+    my $self  = shift;
+    my $field = $self->Argument;
+
+    RT::Logger->error("Field required") unless $field;
+    return unless $field;
+
+    my $DateObj = RT::Date->new($self->TicketObj->CurrentUser);
+    $DateObj->SetToNow;
+    my $value = $DateObj->ISO(Timezone => 'user');
+
+    my ($ret, $msg) = $self->TicketObj->AddCustomFieldValue(Field => $field, Value => $value);
+    unless ($ret) {
+        RT->Logger->error($msg);
+    }
+    return $ret;
+}
+
+RT::Base->_ImportOverlays();
+
+1;
diff --git a/lib/RT/Extension/ChangeManagement.pm b/lib/RT/Extension/ChangeManagement.pm
index d9f6c6d..97e64f4 100644
--- a/lib/RT/Extension/ChangeManagement.pm
+++ b/lib/RT/Extension/ChangeManagement.pm
@@ -181,15 +181,22 @@ Any change that doesn't fall into the other types.
 
 =back
 
-=head3 Deployed Date
-
-Date that the change was successfully deployed (or, partially deployed)
-
 =head3 Rollback Plan
 
 A description of the steps necessary to perform a rollback of the proposed
 changes in the event that the deployment process is unsuccessful.
 
+=head3 Change Started
+
+Date that the change was started. This is B<not> the same as the normal Started
+date on the ticket - Started is set when the ticket is moved to an open status
+(such as approved); Change Started is when someone actually started implementation 
+of the change.
+
+=head3 Change Complete
+
+Date that the change was successfully deployed (or, partially deployed).
+
 =head2 Actions
 
 =head3 Submit Request
@@ -277,6 +284,11 @@ required upon a status change. For example, you may wish to make Implementation
 Validation Steps, and Impact Assessment required fields before a change request can
 be approved.
 
+=head3 Calendar View
+
+With L<RTx::Calendar>, you can add a calendar portlet to your dashboard, as well
+as a full page calendar view of change management tickets and reminders.
+
 =head3 Default Values for Custom Fields
 
 If you look at F<etc/initialdata> in the plugin directory, you will find a section
commit 7e64be22e802fb8099a8d0e658ebd36dce02cb28
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 10 15:26:08 2022 -0500

    Make action name consistent with others

diff --git a/etc/ChangeManagement_Config.pm b/etc/ChangeManagement_Config.pm
index d0be04a..23af68d 100644
--- a/etc/ChangeManagement_Config.pm
+++ b/etc/ChangeManagement_Config.pm
@@ -61,7 +61,7 @@ Set(%Lifecycles,
                 label  => 'Start Deployment',
             },
             'approved -> cancelled' => {
-                label  => 'Cancel Deployment',
+                label  => 'Deployment Cancelled',
             },
             'in progress -> deployed' => {
                 label  => 'Deployment Complete',
commit 5747a20124c3db03bf42429b5e2451e2207369db
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 10 11:55:37 2022 -0500

    Add action: cancel deployment before start

diff --git a/etc/ChangeManagement_Config.pm b/etc/ChangeManagement_Config.pm
index 9e29f19..d0be04a 100644
--- a/etc/ChangeManagement_Config.pm
+++ b/etc/ChangeManagement_Config.pm
@@ -60,6 +60,9 @@ Set(%Lifecycles,
             'approved -> in progress' => {
                 label  => 'Start Deployment',
             },
+            'approved -> cancelled' => {
+                label  => 'Cancel Deployment',
+            },
             'in progress -> deployed' => {
                 label  => 'Deployment Complete',
             },
commit e621f2ce834d310198ac70a97dc576d6738738db
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 10 11:52:42 2022 -0500

    Reorder/recaption CFs; add Change Started

diff --git a/etc/ChangeManagement_Config.pm b/etc/ChangeManagement_Config.pm
index 5b0dbc6..9e29f19 100644
--- a/etc/ChangeManagement_Config.pm
+++ b/etc/ChangeManagement_Config.pm
@@ -2,7 +2,7 @@
 # ticket display
 Set(%CustomFieldGroupings,
     'RT::Ticket' => [
-        'Dates' => ['Change Completed'],
+        'Dates' => ['Change Started','Change Completed'],
         'Change Management' => [
             'Change Category',
             'Change Type',
diff --git a/etc/initialdata b/etc/initialdata
index 49df9bc..6675f3e 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -48,23 +48,32 @@ our @CustomFields = (
         SortOrder   => 2
     },
     {
-        Name        => 'Change Completed',
-        EntryHint   => 'Date when this change the change was completed',
+        Name        => 'Rollback Plan',
+        EntryHint   => 'Explain the backout plan to restore normal operations',
         LookupType  => 'RT::Queue-RT::Ticket',
-        Type        => 'DateTime',
+        Type        => 'Text',
         ApplyTo     => ['Change Management'],
         MaxValues   => 1,
         SortOrder   => 3,
     },
     {
-        Name        => 'Rollback Plan',
-        EntryHint   => 'Explain the backout plan to restore normal operations',
+        Name        => 'Change Started',
+        EntryHint   => 'Date when this change was started',
         LookupType  => 'RT::Queue-RT::Ticket',
-        Type        => 'Text',
+        Type        => 'DateTime',
         ApplyTo     => ['Change Management'],
         MaxValues   => 1,
         SortOrder   => 4,
     },
+    {
+        Name        => 'Change Completed',
+        EntryHint   => 'Date when this change was completed',
+        LookupType  => 'RT::Queue-RT::Ticket',
+        Type        => 'DateTime',
+        ApplyTo     => ['Change Management'],
+        MaxValues   => 1,
+        SortOrder   => 5,
+    },
 );
 
 our @Groups = (
commit 2a9c5024742d518c1ba6a2ee6f9b42412bbf49c2
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 10 11:46:32 2022 -0500

    Show more info on the change mgmt dashboard
    
    Made the dashboard take the full page width, and showed a lot of
    additional details to see what changes need doing and have been done at
    a glance.

diff --git a/etc/initialdata b/etc/initialdata
index 33f7854..49df9bc 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -68,6 +68,10 @@ our @CustomFields = (
 );
 
 our @Groups = (
+    {
+        Name        => 'Change Management',
+        Description => 'People who can create change management tickets and work in change management lifecycle',
+    },
     {
         Name        => 'Change Review Team',
         Description => 'People responsible for approving change requests',
@@ -99,8 +103,8 @@ our @Attributes = (
       Content     =>
       { Format =>  q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',}
                  . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',}
-                 . q{Due,'CF.{Change Type}', 'CF.{Change Category}'},
-        Query    => 'Queue = \'Change Management\' AND Status = \'approved\' AND \'due\' <= \'7 days\'',
+                 . q{Due,'CF.{Change Type}', 'CF.{Change Category}',Priority,'CustomRole.{Change Reviewer}.Name','CustomRole.{Change Implementor}.Name','CF.{Change Started}'},
+        Query    => 'Queue = \'Change Management\' AND ( Status = \'approved\' OR Status = \'in progress\' OR Status = \'partially deployed\' ) AND \'due\' <= \'7 days\'',
         OrderBy  => 'due ASC',
       },
     },
@@ -109,7 +113,7 @@ our @Attributes = (
       Content     =>
       { Format =>  q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',}
                  . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',}
-                 . q{'CF.{Change Completed}','CF.{Change Type}', 'CF.{Change Category}'},
+                 . q{'CF.{Change Type}', 'CF.{Change Category}',Priority,'CustomRole.{Change Reviewer}.Name','CustomRole.{Change Implementor}.Name','CF.{Change Completed}',},
         Query    => 'Queue = \'Change Management\' AND Status = \'deployed\' AND \'CF.{Change Completed}\' >= \'30 days ago\'',
         OrderBy  => 'due ASC',
       },
@@ -177,32 +181,6 @@ our @Final = sub {
             body => [
                 @searches,
             ],
-            sidebar => [
-                {   pane         => 'body',
-                    portlet_type => 'component',
-                    component    => 'QuickCreate',
-                    description  => 'QuickCreate',
-                    path         => '/Elements/QuickCreate',
-                },
-                {   pane         => 'sidebar',
-                    portlet_type => 'component',
-                    component    => 'MyReminders',
-                    description  => 'MyReminders',
-                    path         => '/Elements/MyReminders',
-                },
-                {   pane         => 'sidebar',
-                    portlet_type => 'component',
-                    component    => 'Dashboards',
-                    description  => 'Dashboards',
-                    path         => '/Elements/Dashboards',
-                },
-                {   pane         => 'sidebar',
-                    portlet_type => 'component',
-                    component    => 'RefreshHomepage',
-                    description  => 'RefreshHomepage',
-                    path         => '/Elements/RefreshHomepage',
-                },
-            ]
         };
 
         # fill content
commit 8da31dec8afbabfdc43637d2ecaaa695e6fed21f
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Mon Feb 7 17:28:10 2022 -0500

    Add saved searches, change management dashboard
    
    Items aren't going to show up as completed in the last 30 days unless
    the Change Completed date is filled in, so we need to create a scrip to
    fill that in automatically when deployment completes.

diff --git a/etc/initialdata b/etc/initialdata
index 22cf40e..33f7854 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -89,17 +89,44 @@ our @CustomRoles = (
     },
 );
 
+# 
+# Create some saved searches; these will form the basis of the dashboard below. Add more
+# to suit your organization's needs.
 #
-# This is an example of how to make a custom field have a default value.
-# As most changes will be Standard, it makes sense to use it as the default.
-# You can similarly make other custom fields defined above have default values
-# by providing the name of the custom field to Load (like Change Type is below)
-# and changing Values to be the default value of the field (similar to how Standard
-# is set below).
-#
-# Remember that the custom field name and default values are case sensitive!
-#
+our @Attributes = (
+    { Name => 'Search - Changes Scheduled, Next 7 Days',
+      Description => 'Change management requests due in the next 7 days', # loc
+      Content     =>
+      { Format =>  q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',}
+                 . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',}
+                 . q{Due,'CF.{Change Type}', 'CF.{Change Category}'},
+        Query    => 'Queue = \'Change Management\' AND Status = \'approved\' AND \'due\' <= \'7 days\'',
+        OrderBy  => 'due ASC',
+      },
+    },
+    { Name => 'Search - Changes Deployed, Last 30 Days',
+      Description => 'Change management requests completed in the last 30 days', # loc
+      Content     =>
+      { Format =>  q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',}
+                 . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',}
+                 . q{'CF.{Change Completed}','CF.{Change Type}', 'CF.{Change Category}'},
+        Query    => 'Queue = \'Change Management\' AND Status = \'deployed\' AND \'CF.{Change Completed}\' >= \'30 days ago\'',
+        OrderBy  => 'due ASC',
+      },
+    },
+);
+
 our @Final = sub {
+    #
+    # This is an example of how to make a custom field have a default value.
+    # As most changes will be Standard, it makes sense to use it as the default.
+    # You can similarly make other custom fields defined above have default values
+    # by providing the name of the custom field to Load (like Change Type is below)
+    # and changing Values to be the default value of the field (similar to how Standard
+    # is set below).
+    #
+    # Remember that the custom field name and default values are case sensitive!
+    #
     my $queue_obj = RT::Queue->new(RT->SystemUser);
     my $queue     = 'Change Management';
     $queue_obj->Load($queue);
@@ -118,4 +145,73 @@ our @Final = sub {
     } else {
         die "Could not set default for: ".$cf->Name;
     }
+
+    # Create a change management dashboard.
+    # Combine this with the Calendar extension for an even more informative dashboard experience!
+    my $dashboard = RT::Dashboard->new( RT->SystemUser );
+    ( $ret, $msg ) = $dashboard->Save(
+        Name    => 'Change Management',
+        Privacy => join( '-', ref( RT->System ), RT->System->Id ),
+    );
+
+    if ($ret) {
+        my @searches;
+        for my $search_name ( 'Changes Scheduled, Next 7 Days', 'Changes Deployed, Last 30 Days' ) {
+            my ($search) = RT::System->new( RT->SystemUser )->Attributes->Named( 'Search - ' . $search_name );
+            if ($search) {
+                push @searches,
+                    {
+                    pane         => 'body',
+                    portlet_type => 'search',
+                    id           => $search->Id,
+                    description  => "Saved Search: $search_name",
+                    privacy      => join( '-', ref( RT->System ), RT->System->Id ),
+                    };
+            }
+            else {
+                RT->Logger->error("Couldn't find search $search_name");
+            }
+        }
+
+        my $panes = {
+            body => [
+                @searches,
+            ],
+            sidebar => [
+                {   pane         => 'body',
+                    portlet_type => 'component',
+                    component    => 'QuickCreate',
+                    description  => 'QuickCreate',
+                    path         => '/Elements/QuickCreate',
+                },
+                {   pane         => 'sidebar',
+                    portlet_type => 'component',
+                    component    => 'MyReminders',
+                    description  => 'MyReminders',
+                    path         => '/Elements/MyReminders',
+                },
+                {   pane         => 'sidebar',
+                    portlet_type => 'component',
+                    component    => 'Dashboards',
+                    description  => 'Dashboards',
+                    path         => '/Elements/Dashboards',
+                },
+                {   pane         => 'sidebar',
+                    portlet_type => 'component',
+                    component    => 'RefreshHomepage',
+                    description  => 'RefreshHomepage',
+                    path         => '/Elements/RefreshHomepage',
+                },
+            ]
+        };
+
+        # fill content
+        my ( $ret, $msg ) = $dashboard->Update( Panes => $panes );
+        if ( !$ret ) {
+            RT->Logger->error("Couldn't update content for dashboard Change Management: $msg");
+        }
+    }
+    else {
+        RT->Logger->error("Couldn't create dashboard Change Management: $msg");
+    }
 };
commit 5fddaad8919e8c2cbbf598467c70facac3795847
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 3 16:34:35 2022 -0800

    Clean up action names; set sample default value
    
    Some action names needed to be renamed for clarity. Set a default value
    for change type (most changes are standard changes), and documented how
    users can configure their own default values.

diff --git a/etc/initialdata b/etc/initialdata
index 7a2eb48..22cf40e 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -89,3 +89,33 @@ our @CustomRoles = (
     },
 );
 
+#
+# This is an example of how to make a custom field have a default value.
+# As most changes will be Standard, it makes sense to use it as the default.
+# You can similarly make other custom fields defined above have default values
+# by providing the name of the custom field to Load (like Change Type is below)
+# and changing Values to be the default value of the field (similar to how Standard
+# is set below).
+#
+# Remember that the custom field name and default values are case sensitive!
+#
+our @Final = sub {
+    my $queue_obj = RT::Queue->new(RT->SystemUser);
+    my $queue     = 'Change Management';
+    $queue_obj->Load($queue);
+    die "Failed to load queue $queue" unless $queue_obj->Id;
+
+    my $cf = RT::CustomField->new(RT->SystemUser);
+    my ($ret, $msg) = $cf->Load('Change Type');
+    die $msg unless $ret;
+
+    if ( $cf->id && $cf->SupportDefaultValues ) {
+        ($ret, $msg) = $cf->SetDefaultValues(
+            Object => $queue_obj,
+            Values => 'Standard',
+        );
+        die $msg unless $ret;
+    } else {
+        die "Could not set default for: ".$cf->Name;
+    }
+};
diff --git a/lib/RT/Extension/ChangeManagement.pm b/lib/RT/Extension/ChangeManagement.pm
index 29eda2d..d9f6c6d 100644
--- a/lib/RT/Extension/ChangeManagement.pm
+++ b/lib/RT/Extension/ChangeManagement.pm
@@ -168,7 +168,8 @@ One of the three types of change types outlined in ITIL:
 
 =item Standard 
 
-A low risk, pre-authorized change that follows a repeatable process.
+A low risk, pre-authorized change that follows a repeatable process. This is the
+default for new tickets in the Change Management queue.
 
 =item Emergency
 
@@ -203,15 +204,15 @@ Mark a change management request ticket as approved. Requires the Change Reviewe
 
 Deny the change management request. Requires the Change Reviewer role.
 
-=head3 Start Implementation
+=head3 Start Deployment
 
 Changes the ticket status to in progress. Requires the Change Implementor role.
 
-=head3 Complete Implementation
+=head3 Deployment Complete
 
 Marks the change request as deployed. Requires the Change Implementor role.
 
-=head3 Partially Complete
+=head3 Partially Deployed
 
 Marks the change request as partially deployed. Requires the Change Implementor role.
 
@@ -276,6 +277,25 @@ required upon a status change. For example, you may wish to make Implementation
 Validation Steps, and Impact Assessment required fields before a change request can
 be approved.
 
+=head3 Default Values for Custom Fields
+
+If you look at F<etc/initialdata> in the plugin directory, you will find a section
+called C<@Final> (unsurprisingly, it is the last section of configuration).
+There you will find some sample code and documentation for setting a default value 
+for a custom field.
+
+The process basically boils down to:
+
+=over
+
+=item Load a named queue
+
+=item Load a custom field by name
+
+=item Set the default value for that custom field in that queue
+
+=back
+
 =head2 Approvals Queue
 
 If you have an established Change Review Board, your organization is likely dealing
commit da0432800f62f484d04951083a8edc1c6df22c11
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 3 13:06:32 2022 -0800

    Description changed to entry hints.
    
    This is what I had originally intended them to be, I just used the wrong
    configuration option.

diff --git a/etc/initialdata b/etc/initialdata
index fdef6a0..7a2eb48 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -14,7 +14,7 @@ our @Queues = (
 our @CustomFields = (
     {
         Name        => 'Change Category',
-        Description => 'High-level categorization of the requested change',
+        EntryHint   => 'High-level categorization of the requested change',
         Type        => 'SelectSingle',
         LookupType  => 'RT::Queue-RT::Ticket',
         ApplyTo     => ['Change Management'],
@@ -34,7 +34,7 @@ our @CustomFields = (
     },
     {
         Name        => 'Change Type',
-        Description => 'Kind of service change being requested',
+        EntryHint   => 'Kind of service change being requested',
         LookupType  => 'RT::Queue-RT::Ticket',
         Type        => 'SelectSingle',
         ApplyTo     => ['Change Management'],
@@ -48,8 +48,8 @@ our @CustomFields = (
         SortOrder   => 2
     },
     {
-        Name        => 'Deployed Date',
-        Description => 'Date the change was deployed',
+        Name        => 'Change Completed',
+        EntryHint   => 'Date when this change the change was completed',
         LookupType  => 'RT::Queue-RT::Ticket',
         Type        => 'DateTime',
         ApplyTo     => ['Change Management'],
@@ -58,7 +58,7 @@ our @CustomFields = (
     },
     {
         Name        => 'Rollback Plan',
-        Description => 'Explain the backout plan to restore normal operations',
+        EntryHint   => 'Explain the backout plan to restore normal operations',
         LookupType  => 'RT::Queue-RT::Ticket',
         Type        => 'Text',
         ApplyTo     => ['Change Management'],
commit cd01df58cc64a0e1885b0d0724248e2b1d287eb9
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 3 13:00:48 2022 -0800

    Renamed actions & CFs, require updates for actions
    
    Action names better reflect the change and not the ticket. Some actions
    now require an update - for example, rejecting a change request - the
    reviewer should have to tell the requestor *why* the change was
    rejected.
    
    Partially Deployed now has some actions as it is not necessarily an end
    state. It could be the end, it could be marked failed, etc.

diff --git a/etc/ChangeManagement_Config.pm b/etc/ChangeManagement_Config.pm
index f8f7d54..5b0dbc6 100644
--- a/etc/ChangeManagement_Config.pm
+++ b/etc/ChangeManagement_Config.pm
@@ -2,7 +2,7 @@
 # ticket display
 Set(%CustomFieldGroupings,
     'RT::Ticket' => [
-        'Dates' => ['Deployed Date'],
+        'Dates' => ['Change Completed'],
         'Change Management' => [
             'Change Category',
             'Change Type',
@@ -51,21 +51,40 @@ Set(%Lifecycles,
             },
             'requested -> rejected' => {
                 label  => 'Deny Request',
+                update => 'Respond',
+            },
+            'requested -> cancelled' => {
+                label  => 'Deployment Cancelled',
+                update => 'Respond',
             },
             'approved -> in progress' => {
-                label  => 'Start Implementation',
+                label  => 'Start Deployment',
             },
             'in progress -> deployed' => {
-                label  => 'Complete Implementation',
+                label  => 'Deployment Complete',
             },
             'in progress -> partially deployed' => {
-                label  => 'Partially Complete',
+                label  => 'Partially Deployed',
+                update => 'Respond',
             },
             'in progress -> failed' => {
                 label  => 'Deployment Failed',
+                update => 'Respond',
             },
             'in progress -> cancelled' => {
                 label  => 'Deployment Cancelled',
+                update => 'Respond',
+            },
+            'partially deployed -> deployed' => {
+                label  => 'Deployment Complete',
+            },
+            'partially deployed -> failed' => {
+                label  => 'Deployment Failed',
+                update => 'Respond',
+            },
+            'partially deployed -> cancelled' => {
+                label  => 'Deployment Cancelled',
+                update => 'Respond',
             },
         ]
     },
commit 95081b3d1a6826f982693785ce83362254007af2
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 3 12:02:36 2022 -0800

    Combine config files, remove old lifecycle config

diff --git a/etc/ChangeManagement_Config.pm b/etc/ChangeManagement_Config.pm
index 06bfe15..f8f7d54 100644
--- a/etc/ChangeManagement_Config.pm
+++ b/etc/ChangeManagement_Config.pm
@@ -1,3 +1,5 @@
+# Groups the change management fields together in their own section on the
+# ticket display
 Set(%CustomFieldGroupings,
     'RT::Ticket' => [
         'Dates' => ['Deployed Date'],
@@ -8,3 +10,87 @@ Set(%CustomFieldGroupings,
         ],
     ],
 );
+
+# Creates the change management lifecycle. Allowed status changes, menu actions, 
+# rights, ACLs are defined here. If you're going to make customizations to this
+# extension, most of that work will happen here.
+Set(%Lifecycles,
+    'Change Management' => {
+        initial         => [ qw( requested ) ], # loc_qw
+        active          => [ 'approved', 'in progress', 'partially deployed' ], # loc_qw
+        inactive        => [ qw( deployed failed cancelled rejected deleted ) ], # loc_qw
+        defaults => {
+            on_create   => 'requested',
+        },
+        transitions => {
+            # The following transition is required for ticket creation
+            ''                   => [ qw( requested ) ],
+            requested            => [ qw( approved deployed failed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
+            approved             => [ qw( deployed failed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
+            'in progress'        => [ qw( approved deployed failed cancelled rejected deleted ), 'partially deployed' ],
+            'partially deployed' => [ qw( approved deployed failed cancelled rejected deleted ), 'in progress' ],
+            deployed             => [ qw( approved failed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
+            failed               => [ qw( approved deployed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
+            cancelled            => [ qw( approved deployed failed rejected deleted ), 'in progress', 'partially deployed' ],
+            rejected             => [ qw( approved deployed failed cancelled deleted ), 'in progress', 'partially deployed' ],
+        },
+        rights => {
+            'requested -> approved'             => 'Change Reviewer',
+            'requested -> rejected'             => 'Change Reviewer',
+            'approved -> in progress'           => 'Change Implementor',
+            'in progress -> deployed'           => 'Change Implementor',
+            'in progress -> partially deployed' => 'Change Implementor',
+            'in progress -> failed'             => 'Change Implementor',
+        },
+        actions => [
+            '* -> requested' => {
+                label  => 'Submit Request',
+            },
+            'requested -> approved' => {
+                label  => 'Approve Request',
+            },
+            'requested -> rejected' => {
+                label  => 'Deny Request',
+            },
+            'approved -> in progress' => {
+                label  => 'Start Implementation',
+            },
+            'in progress -> deployed' => {
+                label  => 'Complete Implementation',
+            },
+            'in progress -> partially deployed' => {
+                label  => 'Partially Complete',
+            },
+            'in progress -> failed' => {
+                label  => 'Deployment Failed',
+            },
+            'in progress -> cancelled' => {
+                label  => 'Deployment Cancelled',
+            },
+        ]
+    },
+    __maps__ => {
+        'default -> Change Management' => {
+            'new'         => 'requested',
+            'resolved'    => 'deployed',
+            'open'        => 'in progress',
+            'rejected'    => 'rejected',
+            'open'        => 'partially deployed',
+            'deleted'     => 'deleted',
+        },
+        'Change Management -> default' => {
+            'requested'          => 'new',
+            'deployed'           => 'resolved',
+            'rejected'           => 'rejected',
+            'deleted'            => 'deleted',
+            'in progress'        => 'open',
+            'approved'           => 'open',
+            'partially deployed' => 'open', 
+            'failed'             => 'resolved',
+            'cancelled'          => 'resolved',
+        },
+    }
+);
+
+1;
+
diff --git a/etc/Lifecycle_config.pm b/etc/Lifecycle_config.pm
deleted file mode 100644
index c1f8578..0000000
--- a/etc/Lifecycle_config.pm
+++ /dev/null
@@ -1,80 +0,0 @@
-Set(%Lifecycles,
-    'Change Management' => {
-        initial         => [ qw( requested ) ], # loc_qw
-        active          => [ 'approved', 'in progress', 'partially deployed' ], # loc_qw
-        inactive        => [ qw( deployed failed cancelled rejected deleted ) ], # loc_qw
-        defaults => {
-            on_create   => 'requested',
-        },
-        transitions => {
-            # The following transition is required for ticket creation
-            ''                   => [ qw( requested ) ],
-            requested            => [ qw( approved deployed failed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
-            approved             => [ qw( deployed failed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
-            'in progress'        => [ qw( approved deployed failed cancelled rejected deleted ), 'partially deployed' ],
-            'partially deployed' => [ qw( approved deployed failed cancelled rejected deleted ), 'in progress' ],
-            deployed             => [ qw( approved failed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
-            failed               => [ qw( approved deployed cancelled rejected deleted ), 'in progress', 'partially deployed' ],
-            cancelled            => [ qw( approved deployed failed rejected deleted ), 'in progress', 'partially deployed' ],
-            rejected             => [ qw( approved deployed failed cancelled deleted ), 'in progress', 'partially deployed' ],
-        },
-        rights => {
-            'requested -> approved'             => 'Change Reviewer',
-            'requested -> rejected'             => 'Change Reviewer',
-            'approved -> in progress'           => 'Change Implementor',
-            'in progress -> deployed'           => 'Change Implementor',
-            'in progress -> partially deployed' => 'Change Implementor',
-            'in progress -> failed'             => 'Change Implementor',
-        },
-        actions => [
-            '* -> requested' => {
-                label  => 'Submit Request',
-            },
-            'requested -> approved' => {
-                label  => 'Approve Request',
-            },
-            'requested -> rejected' => {
-                label  => 'Deny Request',
-            },
-            'approved -> in progress' => {
-                label  => 'Start Implementation',
-            },
-            'in progress -> deployed' => {
-                label  => 'Complete Implementation',
-            },
-            'in progress -> partially deployed' => {
-                label  => 'Partially Complete',
-            },
-            'in progress -> failed' => {
-                label  => 'Deployment Failed',
-            },
-            'in progress -> cancelled' => {
-                label  => 'Deployment Cancelled',
-            },
-        ]
-    },
-    __maps__ => {
-        'default -> Change Management' => {
-            'new'         => 'requested',
-            'resolved'    => 'deployed',
-            'open'        => 'in progress',
-            'rejected'    => 'rejected',
-            'open'        => 'partially deployed',
-            'deleted'     => 'deleted',
-        },
-        'Change Management -> default' => {
-            'requested'          => 'new',
-            'deployed'           => 'resolved',
-            'rejected'           => 'rejected',
-            'deleted'            => 'deleted',
-            'in progress'        => 'open',
-            'approved'           => 'open',
-            'partially deployed' => 'open', 
-            'failed'             => 'resolved',
-            'cancelled'          => 'resolved',
-        },
-    }
-);
-
-1;
-
commit 3f72053b28839de11d6b42f71e710908219c2aef
Author: Jason Crome <jcrome at bestpractical.com>
Date:   Thu Feb 3 12:00:11 2022 -0800

    Fix POD errors
    
    The missing initdb section is, as far as I am concerned, a bug, and
    therefore lumping it in with this commit.

diff --git a/lib/RT/Extension/ChangeManagement.pm b/lib/RT/Extension/ChangeManagement.pm
index 26d7cce..29eda2d 100644
--- a/lib/RT/Extension/ChangeManagement.pm
+++ b/lib/RT/Extension/ChangeManagement.pm
@@ -24,12 +24,17 @@ Works with RT 5.
 
 May need root permissions
 
-=item Edit your F</opt/rt4/etc/RT_SiteConfig.pm>
+=item Edit your F</opt/rt5/etc/RT_SiteConfig.pm>
 
 Add this line:
 
     Plugin('RT::Extension::ChangeManagement');
 
+=item C<make initdb>
+
+Only run this the first time you install this module. If you run this twice, 
+you may end up with duplicate data in your database.
+
 =item Clear your mason cache
 
     rm -rf /opt/rt5/var/mason_data/obj
@@ -55,7 +60,7 @@ can transform into a fully-featured change management system.
 
 =head2 Change Management Queue
 
-After installing, you'll see a new queue called L<Change Management> for tracking
+After installing, you'll see a new queue called B<Change Management> for tracking
 all of the incoming change requests. You can change the name to anything you like 
 after installing. In a typical configuration, you will also want to assign an RT 
 email address, like changes at example.com or crb at example.com (Change Review Team)
@@ -129,8 +134,6 @@ comment on the ticket.
 
 =back
 
-=head2 Change Management Lifecycle
-
 =head2 Custom Fields
 
 =head3 Change Category
-----------------------------------------------------------------------

Summary of changes:
 etc/ChangeManagement_Config.pm       | 133 +++++++++++++++++++++-
 etc/Lifecycle_config.pm              |  80 -------------
 etc/initialdata                      | 211 +++++++++++++++++++++++++++++++++--
 lib/RT/Action/SetCustomFieldDate.pm  |  32 ++++++
 lib/RT/Extension/ChangeManagement.pm |  80 ++++++++-----
 5 files changed, 418 insertions(+), 118 deletions(-)
 delete mode 100644 etc/Lifecycle_config.pm
 create mode 100644 lib/RT/Action/SetCustomFieldDate.pm


hooks/post-receive
-- 
rt-extension-changemanagement


More information about the Bps-public-commit mailing list