Subversion Repositories DevTools

Rev

Rev 4698 | Rev 5586 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4625 dpurdie 1
########################################################################
2
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
3
#
4
# Module name   : process_release_notes.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Poll RM and generate Release Notes as required
10
#                 Must run on the same machine as the package archive
11
#                 It directly manipulates the target package
12
#                 Requires access to the machines sudo mechism
13
#
14
# Usage         : See POD at the end of this file
15
#
16
#......................................................................#
17
 
18
require 5.008_002;
19
 
20
use strict;
21
use warnings;
22
use JatsError;
23
use JatsSystem;
24
use Getopt::Long;
25
use Pod::Usage;                             # required for help support
26
use File::Temp qw/ tempfile tempdir /;
27
use LWP::UserAgent;
28
use HTTP::Request::Common 'POST';
29
use Fcntl ':flock';
30
use FindBin;                                # Determine the current directory
31
 
32
use JatsEnv;
33
use JatsRmApi;
34
use FileUtils;
35
 
36
use DBI;
37
 
38
my $VERSION = "1.0.0";                      # Update this
39
my $GBE_DPKG = $ENV{GBE_DPKG};              # Sanitised by Jats
4698 dpurdie 40
my $GBE_RM_URL = $ENV{GBE_RM_URL};
4625 dpurdie 41
my $RM_DB;
42
my $tempdir;
43
my $sudoUtilsDir = '/home/releasem/sbin';
44
my $lockFile = '/tmp/JATSRN_LOCK';
45
my $scriptDir = "$FindBin::Bin";
46
 
47
#
48
#   Options
49
#
50
my $opt_verbose = 0;
51
my $opt_help = 0;
52
my $opt_age = 2;
53
my $opt_keepTemp = 0;
54
my $opt_status = 0;
55
my $opt_pvid;
56
 
57
#
58
#   Package information
59
#
60
my @Packages;
4706 dpurdie 61
my @packageItems = qw( PV_ID RTAG_ID NAME VERSION PKG_ID PROJ_ID RNINFO BUILD_TYPE BS_ID);
4625 dpurdie 62
my %rmConfig;
63
 
64
#-------------------------------------------------------------------------------
65
# Function        : Main Entry
66
#
67
# Description     :
68
#
69
# Inputs          :
70
#
71
# Returns         :
72
#
73
my $result = GetOptions (
74
                'help+'         => \$opt_help,          # flag, multiple use allowed
75
                'manual:3'      => \$opt_help,          # flag
76
                'verbose:+'     => \$opt_verbose,       # flag
77
                'age:i'         => \$opt_age,           # Number
78
                'keeptemp!'     => \$opt_keepTemp,      # flag
79
                'status+'       => \$opt_status,        # flag
80
                'pvid:i'        => \$opt_pvid,          # Number
81
                );
82
 
83
#
84
#   Process help and manual options
85
#
86
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
87
pod2usage(-verbose => 1)  if ($opt_help == 2);
88
pod2usage(-verbose => 2)  if ($opt_help > 2);
89
 
90
ErrorConfig( 'name'    =>'RelNotes', 
91
             'verbose' => $opt_verbose );
92
$opt_verbose-- if ($opt_verbose > 0);
93
#
94
#   Sanity Test
95
#
96
Error("Not running on a Unix System") unless ($ENV{GBE_UNIX});
97
Error("Sudo Utils not found: $sudoUtilsDir") unless ( -d $sudoUtilsDir);
98
Warning("Not running as a sutable user" ) unless ($ENV{USER} eq 'buildadm' || $ENV{USER} eq 'releasem');
99
EnvImport ('GBE_PERL');
100
 
101
#
102
#   Ensure only one instance is running
103
#   PerlMonks say to use $0 as the lock file, but that did not work.
104
#   Perhaps the file was open in an editor
105
#   Solution: Create my own file
106
#
107
open( FW, '>',$lockFile);
108
print FW '';
109
close FW;
110
 
111
open (my $self, '<', $lockFile) || Error("Couldn't open self: $!");
112
flock ($self, (LOCK_EX | LOCK_NB)) || Error("This script is already running");
113
 
114
#
115
#   Init parameters
116
#
117
$tempdir = tempdir('/tmp/JATSRN_XXXXXX',CLEANUP => !$opt_keepTemp);
118
Warning("Need to remove tempdir: " . DisplayPath($tempdir)) if $opt_keepTemp;
119
Verbose("Tempdir:" , DisplayPath($tempdir));
120
Verbose("scriptDir:" , DisplayPath($scriptDir));
121
 
122
#   Force GBE_ABT. Currently the Release Manager proxy password only works
123
#   When used in this mode
124
$ENV{GBE_ABT} = 1 unless defined $ENV{GBE_ABT};
125
 
126
#
127
#   User RW password, if provided
128
#
129
$ENV{GBE_RM_USERNAME} = $ENV{GBE_RM_USERNAME_RW} if (exists $ENV{GBE_RM_USERNAME_RW});
130
$ENV{GBE_RM_PASSWORD} = $ENV{GBE_RM_PASSWORD_RW} if (exists $ENV{GBE_RM_PASSWORD_RW});
131
 
132
if ($ENV{GBE_ABT} && $ENV{GBE_RM_USERNAME} && $ENV{GBE_RM_USERNAME} !~ m~]$~ )
133
{
134
    Verbose("Access RM database as proxy user");
135
    $ENV{GBE_RM_USERNAME} = $ENV{GBE_RM_USERNAME} . '[release_manager]'; 
136
}
137
 
138
#
139
#   Interogate the RM database and locate packages that need to be processed
140
#
141
$opt_pvid ? LocatePackagesByPvid() : LocatePackages();
142
Verbose("Package to process:" . scalar @Packages);
143
#DebugDumpData("Packages", \@Packages);
144
 
145
#
146
#   Process each found entry
147
#
148
foreach my $entry ( @Packages)
149
{
150
    GenerateReleaseNote( $entry);
151
}
152
 
153
unlink $lockFile;
154
exit 0;
155
 
156
#-------------------------------------------------------------------------------
157
# Function        : LocatePackages 
158
#
159
# Description     : Locate packages in need of Release Notes
160
#
161
# Inputs          : None
162
#
163
# Returns         : Nothing
164
#                   Populates the @Packages array
165
#
166
sub LocatePackages
167
{
168
    my $m_sqlstr =
169
            "SELECT * from
170
            (
171
                SELECT pv.pv_id, 
172
                       rc.rtag_id, 
173
                       pkg.pkg_name, 
174
                       pv.pkg_version, 
175
                       pv.pkg_id, 
176
                       rt.proj_id , 
177
                       pv.release_notes_info,
4706 dpurdie 178
                       pv.build_type,
179
                       pv.BS_ID,
4625 dpurdie 180
                       TRUNC(sysdate - pv.modified_stamp ) AS age , 
181
                       row_number() OVER (PARTITION BY pv.pv_id, pkg.pkg_name, pv.pkg_version ORDER BY rc.rtag_id) rn
182
                FROM release_manager.package_versions pv, 
183
                     release_manager.release_content rc, 
184
                     release_manager.packages pkg, 
185
                     release_manager.release_tags rt
186
                WHERE pv.pv_id = rc.pv_id
187
                AND pkg.pkg_id = pv.pkg_id
188
                AND rc.rtag_id = rt.rtag_id
189
                AND pv.pv_id IN (SELECT pv_id 
190
                                 FROM release_manager.package_versions 
191
                                 WHERE (release_notes_info IS null 
4706 dpurdie 192
                                     OR (release_notes_info like 'MSG:%' AND release_notes_info != 'MSG:5' ))
4625 dpurdie 193
                                 AND pv.dlocked = 'Y'
194
                                 AND pv.modified_stamp > (sysdate - $opt_age)
195
                                 )
196
            )
197
            where rn = 1";
198
 
199
    populateArrayFromSql('LocatePackages', \@Packages, $m_sqlstr, \@packageItems);
200
#    DebugDumpData("Packages", \@Packages);
201
}
202
 
203
#-------------------------------------------------------------------------------
204
# Function        : LocatePackagesByPvid 
205
#
206
# Description     : Locate one package, as specified by its PVID
207
#                   This mode is only used in testing  
208
#
209
# Inputs          : Global: $opt_pvid 
210
#
211
# Returns         : Populate the @Packages array
212
#
213
sub LocatePackagesByPvid
214
{
215
    #   Extract: PV_ID RTAG_ID NAME VERSION PKG_ID PROJ_ID RNINFO AGE 
216
    my $m_sqlstr = "
217
                SELECT pv.pv_id, 
218
                       rc.rtag_id, 
219
                       pkg.pkg_name, 
220
                       pv.pkg_version, 
221
                       pv.pkg_id, 
222
                       rt.proj_id, 
4706 dpurdie 223
                       pv.release_notes_info,
224
                       pv.build_type,
225
                       pv.BS_ID
4625 dpurdie 226
                FROM release_manager.package_versions pv, 
227
                     release_manager.release_content rc, 
228
                     release_manager.packages pkg, 
229
                     release_manager.release_tags rt
230
                WHERE pv.pv_id = rc.pv_id
231
                AND pkg.pkg_id = pv.pkg_id
232
                AND rc.rtag_id = rt.rtag_id
233
                AND pv.pv_id = $opt_pvid
234
                ";
235
 
236
    populateArrayFromSql('LocatePackagesByPvid', \@Packages, $m_sqlstr, \@packageItems);
237
    #DebugDumpData("Packages", \@Packages);
238
}
239
 
240
#-------------------------------------------------------------------------------
241
# Function        : GenerateReleaseNote  
242
#
243
# Description     : Generate One Release Note
244
#                   Invoke several JATS utilities to do the hard work
245
#
246
# Inputs          : $entry          - Hash of useful infomation
247
#
248
# Returns         : Nothing
249
#                   Will exit on error
250
#
251
sub GenerateReleaseNote
252
{
253
    my ($entry) = @_;
254
    my $outfile;
255
    my $rv;
256
    my @args;
257
 
258
    #DebugDumpData("Entry", $entry);
259
    Message("-------------------- $entry->{NAME}, $entry->{VERSION}") if $opt_status || $opt_verbose;
260
 
261
    my $pkgBase = catdir($GBE_DPKG, $entry->{NAME}, $entry->{VERSION});
262
    Verbose("Processing: $pkgBase");
263
 
264
    #
4706 dpurdie 265
    #   Handle special class of packages
266
    #       Manually Built
267
    #       No Build Standard
268
    #       Not in dpkg_archive
269
    #   Example: unit_test_br_kcm_ct_saftp
270
    #   This type of package appears to be a place holder
271
    #   Still needs some level of processing
4625 dpurdie 272
    #
4706 dpurdie 273
    if ($entry->{BUILD_TYPE}  eq 'M' && $entry->{BS_ID} == 3 && ! -d $pkgBase)
274
    {
275
        Verbose ("Placeholder package detected");
276
        #DebugDumpData("Entry", $entry);
277
        updatePlaceHolderRmNoteInfo($entry);
278
        $rv = 0;
279
    }
280
    else
281
    {
282
        #
283
        #
284
        unless (-d $pkgBase) {
285
            Warning("Package not in archive: $pkgBase");
286
            return;
287
        }
4625 dpurdie 288
 
4706 dpurdie 289
        #
290
        #   Make the target Package Version Writable and Ensure that the doc directory
291
        #   exists. This is done via a script that is invoked with SUDO, partially to
292
        #   interwork with the existing system  
293
        #
294
        runSudoCommand('make_writable', 'dpkg_archive', $entry->{NAME},$entry->{VERSION});
295
        runSudoCommand('make_docFolder', 'dpkg_archive', $entry->{NAME},$entry->{VERSION}, 'doc');
4625 dpurdie 296
 
4706 dpurdie 297
        #
298
        #   Get the basic data required for the Release Note
299
        #   jats jats_get_releasenote_data.pl -pvid=1002782
300
        #
301
        $outfile = catdir($tempdir, join('_',$entry->{NAME},$entry->{VERSION})) . '.xml';
302
        $rv = localTool('jats_get_releasenote_data', '-verbose', $opt_verbose, '-pvid', $entry->{PV_ID}, '-outfile', $outfile );
303
 
304
        #
305
        #   Generate the actual release note and update the Release Manager
306
        #   jats jats_gen_releasenote.pl -releasenote=mcrdemo_1.2.3157.cr.xml -UpdateRmFiles
307
        unless ($rv)
308
        {
309
            $rv = localTool('jats_gen_releasenote.pl', '-verbose', $opt_verbose, '-UpdateRmFiles', '-releasenote', $outfile);
310
        }
311
 
312
        #
313
        #   Release note complete - or failed
314
        #       Make the target PackageVersion ReadOnly
315
        #       Signal End of Package Processing - which will trigger blat
316
        #
317
        #   Do this even if we have a Release Note Failure
318
        #
319
        runSudoCommand('make_readonly', 'dpkg_archive', $entry->{NAME},$entry->{VERSION});
4625 dpurdie 320
    }
321
 
322
    #    make_release_changed 
323
    #       archive=archive-path 
4632 dpurdie 324
    #       pkg_name="package-name" 
325
    #       pkg_version="package-version" 
4625 dpurdie 326
    #       rtag_id=release-tag-id 
327
    #       pkg_id=package-id 
328
    #       pv_id=package-version-id 
329
    #       proj_id=project-id 
330
    #       mode_id=change-mode-id (1 pkg added, 2 pkg removed, 3 pkg released)
331
    #
4632 dpurdie 332
    #   Note: The ReleasedPackagereport tool parses the make_released_changed entries
333
    #         It requires quotes on the pkg_name and pkg_version for correct parsing
334
    #
4625 dpurdie 335
    push @args, 'archive=dpkg_archive';
336
    push @args, 'mode_id=3';
4632 dpurdie 337
    push @args, 'pkg_name="'    . $entry->{NAME} . '"';
338
    push @args, 'pkg_version="' . $entry->{VERSION} . '"';
4625 dpurdie 339
    push @args, 'rtag_id='     . $entry->{RTAG_ID};
340
    push @args, 'pkg_id='      . $entry->{PKG_ID};
341
    push @args, 'pv_id='       . $entry->{PV_ID};
342
    push @args, 'proj_id='     . $entry->{PROJ_ID};
343
 
344
    runSudoCommand('make_release_changed', @args);
345
 
346
    #
347
    #   Email interested users
348
    #
349
    notifyInterestedUsers($entry);
350
 
351
    Error ("Did not generate Release Note: $entry->{NAME}, $entry->{VERSION}") if ($rv);
352
}
353
 
354
#-------------------------------------------------------------------------------
4706 dpurdie 355
# Function        : updatePlaceHolderRmNoteInfo 
356
#
357
# Description     : Insert Release Note Info into the Release Manager Database
358
#                   This has the side effect that RM will see the Release Note
359
#                   as being fully generated.
360
#
361
#                   Used only by special PlaceHolder packages
362
#
363
# Inputs          : $entry          - Hash of useful infomation
364
#
365
# Returns         : 
366
#
367
sub updatePlaceHolderRmNoteInfo
368
{
369
    my ($entry) = @_;
370
 
371
    executeRmQuery (
372
        'updateRmNoteInfo', 
373
        'update release_manager.package_versions set release_notes_info=\'MSG:5\' where pv_id=' . $entry->{PV_ID}
374
        );
375
}
376
 
377
#-------------------------------------------------------------------------------
4625 dpurdie 378
# Function        : localTool 
379
#
380
# Description     : Run a jats tool from the same directory as this script 
381
#
382
# Inputs          : $name           - Name of the script
383
#                   ...             - Arguments for the command
384
#
385
# Returns         : 
386
#
387
sub localTool
388
{
389
    my $cmd = shift;
390
    $cmd .= '.pl' unless ( $cmd =~ m~\.pl$~i );
391
    $cmd = catdir($scriptDir, $cmd);
392
    Error ("Command not found: $cmd") unless -f $cmd;
393
 
394
    return System ( '--NoShell', $::GBE_PERL, $cmd, @_ );
395
}
396
 
397
 
398
#-------------------------------------------------------------------------------
399
# Function        : notifyInterestedUsers  
400
#
401
# Description     : A user can register interest in a package (name) being built in a 
402
#                   specific Project 
403
#                   Perhaps this should be done by the build tool, but at the moment 
404
#                   this release note generation process is really a part of the build
405
#
406
#                   NOTE: Similar code exists in the RM web server to handle manually
407
#                         released packages.
408
#                   
409
# Inputs          : $entry          - Hash of useful infomation
410
#
411
# Returns         : 
412
#
413
sub notifyInterestedUsers
414
{
415
    my ($entry) = @_;
416
    my @userList;
417
 
418
    #
419
    #   Determine interested users
420
    #
421
    my $m_sqlstr = "SELECT U.user_email, prj.proj_name, rt.rtag_name, pkg.pkg_name, pv.pkg_version ,pv.pv_id, rt.rtag_id
4706 dpurdie 422
        FROM RELEASE_MANAGER.PACKAGE_INTEREST PI, 
423
             RELEASE_MANAGER.PACKAGES PKG, 
424
             RELEASE_MANAGER.PACKAGE_VERSIONS PV, 
425
             RELEASE_MANAGER.USERS U,
426
             RELEASE_MANAGER.RELEASE_TAGS RT, 
427
             RELEASE_MANAGER.PROJECTS PRJ 
4625 dpurdie 428
        WHERE PKG.PKG_ID = PI.PKG_ID 
429
          AND RT.RTAG_ID = $entry->{RTAG_ID}
430
          AND PV.PV_ID = $entry->{PV_ID}
431
          AND PV.PKG_ID = PKG.PKG_ID 
432
          AND PRJ.PROJ_ID = RT.PROJ_ID 
433
          AND PRJ.PROJ_ID = PI.PROJ_ID 
434
          AND U.USER_ID = PI.USER_ID";
435
 
436
    my @items = qw( USER_EMAIL PROJ_NAME RTAG_NAME PKG_NAME PKG_VERSION PV_ID RTAG_ID );
437
 
438
    populateArrayFromSql('notifyInterestedUsers', \@userList, $m_sqlstr, \@items);
439
 
440
    #
441
    #   Do we have something to do
442
    #
443
    return unless (@userList);
444
    #DebugDumpData("userList", \@userList);
445
 
446
    #   Ensure we have basic emailing information
447
    #
448
    getRmConfig();
449
 
450
    #
451
    #   Send Email to all the required users
452
    #   Note: This emailer requires a sendmail utility
453
    #
454
    foreach my $entry ( @userList)
455
    {
456
        #$entry->{USER_EMAIL} = 'dpurdie@vixtechnology.com';
457
        #Debug0("Sending email to David Purdie indead of real user");
458
 
4698 dpurdie 459
        my $rnUrl = $GBE_RM_URL . "/fixed_issues.asp?pv_id=$entry->{PV_ID}&rtag_id=$entry->{RTAG_ID}";
4625 dpurdie 460
        my $subject = "Package Release Notification: $entry->{PKG_NAME} $entry->{PKG_VERSION}";
4698 dpurdie 461
        my $content = "Version <a href='$rnUrl'>$entry->{PKG_VERSION}</a> of Package $entry->{PKG_NAME} in Project $entry->{PROJ_NAME} on Release Branch $entry->{RTAG_NAME} has been released.";
462
           $content .= "<p>Package Link: $rnUrl";
4625 dpurdie 463
           $content .= "<p>You have received this email as a result of your interest in this package. If you do not wish to receive further emails then remove your package interest from the notifications area in Release Manager.";
464
 
465
 
466
        my $req = POST( 'mailto:' . $entry->{USER_EMAIL},
467
            From         => $rmConfig{'BUILD FAILURE MAIL SENDER'},
468
            CC           => 'buildadm@vixtechnology.com',
469
            Date         => scalar localtime,
470
            Subject      => $subject,
471
            Content_Type => qq(text/html),
472
            Content      => $content,
473
        );
474
 
475
        my $response = LWP::UserAgent->new->request($req);
476
        if ($response->code != 202)
477
        {
478
            Warning("Email Send Error: $response->code");
479
            #DebugDumpData("Response", \$response);
480
        }
481
    }
482
}
483
 
484
 
485
#-------------------------------------------------------------------------------
486
# Function        : getRmConfig 
487
#
488
# Description     : Get Basic config from Release Manager
489
#                   Only do it once
490
#
491
#                   Just need:
492
#                       'BUILD FAILURE MAIL SENDER'
493
#                       'MAIL SERVER'
494
#
495
# Inputs          : None
496
#
497
# Returns         : Populates a global hash
498
#
499
sub getRmConfig
500
{
501
    return if keys(%rmConfig) > 0;
502
    my $m_sqlstr = "SELECT * from BUILD_SERVICE_CONFIG";
503
 
504
    performSqlQueryCallback('getRmConfig', 
505
                            $m_sqlstr, 
506
                            sub { 
507
                                my ($pRow) = @_;
508
                                $rmConfig{ $pRow->[0] } = $pRow->[1];
509
                                }
510
                            );
511
#DebugDumpData("rmConfig", \%rmConfig);
512
}
513
 
514
 
515
#-------------------------------------------------------------------------------
516
# Function        : runSudoCommand 
517
#
518
# Description     : Run a Unix command as root via the sodo system
519
#                   Requires that target commands be available
520
#                   Requires sudo to be configured to allow this user to run them
521
#
522
# Notes           : The sudoers file on the archive server needs to be configured to allow:
523
#                       This user to run programs from /home/releasem/sbin without a password
524
#                       The users sudo credentials must not timeout (or be used)
525
#
526
# Inputs          : prog            - Command to run
527
#                   arguments       - Command arguments
528
#
529
# Returns         : Nothing 
530
#
531
sub runSudoCommand
532
{
533
    my ($prog, @arguments) = @_;
534
    my $cmd;
535
    my $rv;
536
 
537
    #
538
    #   Construct command
539
    #
540
    $cmd = catdir($sudoUtilsDir, $prog);
541
    $rv = System('--NoShell','sudo','-n', $cmd, @arguments);
542
    Warning("SudoCmd Result: $prog: $rv") if ($rv);
543
}
544
 
545
#-------------------------------------------------------------------------------
546
# Function        : performSqlQueryCallback 
547
#
548
# Description     : Perform a general Sql query and invoke a user function for
549
#                   each row of results
550
#
551
# Inputs          : $fname                  - Name of query for error reporting
552
#                   $m_sqlstr               - Query string
553
#                   $f_process              - Function called for each row in the result
554
#                                             Use closure to have callback modify other data
555
#
556
# Returns         : Number of rows found
557
#
558
sub performSqlQueryCallback
559
{
560
    my ($fname, $m_sqlstr, $f_process ) = @_;
561
    my $found = 0;
562
 
563
    #
564
    #   Connect to the database - once
565
    #
566
    connectRM(\$RM_DB, $opt_verbose) unless $RM_DB;
567
 
568
    $m_sqlstr =~ s~\s+~ ~g;
569
    Verbose3("SQL:", $m_sqlstr);
570
    my $sth = $RM_DB->prepare($m_sqlstr);
571
    if ( defined($sth) )
572
    {
573
        if ( $sth->execute( ) )
574
        {
575
            if ( $sth->rows )
576
            {
577
                while ( my @row = $sth->fetchrow_array )
578
                {
579
                    $found++;
580
                    &$f_process(\@row);
581
                }
582
            }
583
            $sth->finish();
584
        }
585
        else
586
        {
587
            Error("$fname:Execute failure: $m_sqlstr", $sth->errstr() );
588
        }
589
    }
590
    else
591
    {
592
        Error("$fname:Prepare failure" );
593
    }
594
 
595
    unless ( $found )
596
    {
597
        Verbose("$fname:No data found");
598
    }
599
    return $found;
600
}
601
 
602
#-------------------------------------------------------------------------------
603
# Function        : populateArrayFromSql 
604
#
605
# Description     : Issue an SQL query and push the results into an array of hashes
606
#                   where each row from the query is a hash and the entire result is an 
607
#                   array 
608
#
609
# Inputs          :     name                - For error reporting
610
#                       pArray              - Ref to the output array
611
#                       sql                 - Sql to process
612
#                       pItems              - Array of tems to extract
613
#                                             Must match the SQL SELECT arguments
614
#                                             Item names starting with '-' do not end up in the
615
#                                             generated XML
616
# Returns         : 
617
#
618
sub populateArrayFromSql
619
{
620
    my ($fname, $pArray, $m_sqlstr, $pItems) = @_;
621
 
622
    performSqlQueryCallback($fname, 
623
                            $m_sqlstr, 
624
                            sub { 
625
                                my ($pRow) = @_;
626
                                my %entry;
627
                                push @{$pArray}, populateHash( \%entry, $pRow, $pItems);
628
                                }
629
                            );
630
#DebugDumpData("populateArrayFromSql", $pArray);
631
}
632
 
633
#-------------------------------------------------------------------------------
634
# Function        : populateHash 
635
#
636
# Description     : Put an array of data items into a hash
637
#
638
# Inputs          : pHash           - ref to output hash
639
#                   pRow            - Ref to the row data 
640
#                   pItems          - Ref to an hash array of entry names
641
#
642
# Returns         : pHash
643
#
644
sub populateHash
645
{
646
    my ($pHash, $pRow, $pItems) = @_;
647
 
648
    foreach my $item ( @{$pItems} ) {
649
        my $data = shift @{$pRow};
650
 
651
        if (defined $data)
652
        {
653
            $data =~ s~^\s+~~;
654
            $data =~ s~\s+$~~;
655
 
656
            #
657
            #   Store in hash
658
            #
659
            $pHash->{$item} = $data;
660
        }
661
    }
662
    return $pHash;
663
}
664
 
665
#-------------------------------------------------------------------------------
4706 dpurdie 666
# Function        : executeRmQuery 
667
#
668
# Description     : Execute a simple RM query. One that does not expect any return data
669
#
670
# Inputs          : $fname           - OprName, for error reporting
671
#                   $m_sqlstr        - SQL String
672
#
673
# Returns         : Will exit on error
674
#
675
sub executeRmQuery
676
{
677
    my ($fname, $m_sqlstr) = @_;
678
 
679
    #
680
    #   Connect to the Database - once
681
    #
682
    connectRM(\$RM_DB, 0) unless $RM_DB;
683
 
684
    Verbose2('ExecuteQuery:', $fname);
685
    #
686
    #   Create the full SQL statement
687
    #
688
    my $sth = $RM_DB->prepare($m_sqlstr);
689
    if ( defined($sth) )
690
    {
691
        if ( $sth->execute() )
692
        {
693
            $sth->finish();
694
        }
695
        else
696
        {
697
            Error("$fname: Execute failure: $m_sqlstr", $sth->errstr() );
698
        }
699
    }
700
    else
701
    {
702
        Error("$fname: Prepare failure");
703
    }
704
}
705
 
706
#-------------------------------------------------------------------------------
4625 dpurdie 707
#   Documentation
708
#
709
 
710
=pod
711
 
712
=for htmltoc    SYSUTIL::
713
 
714
=head1 NAME
715
 
716
process_release_notes - Create Release Notes for newly created packages
717
 
718
=head1 SYNOPSIS
719
 
720
 jats process_release_notes [options]
721
 
722
 Options:
723
    -help              - Brief help message
724
    -help -help        - Detailed help message
725
    -man               - Full documentation
726
    -verbose           - Display additional progress messages
727
    -pvid=nn           - PVID of package to process(test mode)
728
    -age=nn            - Examine packages created in last n days
729
    -keeptemp          - Keep the temp workspace
730
    -status            - Display status
731
 
732
=head1 OPTIONS
733
 
734
=over 8
735
 
736
=item B<-help>
737
 
738
Print a brief help message and exits.
739
 
740
=item B<-help -help>
741
 
742
Print a detailed help message with an explanation for each option.
743
 
744
=item B<-man>
745
 
746
Prints the manual page and exits.
747
 
748
=item B<-pvid=nn>
749
 
750
This option bypasses the normal mechanism of determining packages to be processed and 
751
will process just the specified package. This is normally only used to test the operation 
752
of the subsystem.
753
 
754
=item B<-age=nn>
755
 
756
This option control the period of time period used in determing which packages to process. 
757
 
758
The number is in days. The default value is 2 days.
759
 
760
=item B<-keeptemp>
761
 
762
If this option is specified, then the temporary directory created in the processing will be 
763
retained. The user is responsible for deleting the directory.
764
 
765
This option is normally only used in testing.
766
 
767
=item B<-status>
768
 
769
When set, this option will cause the program to display the package name and version of each
770
package being processed.
771
 
772
=back
773
 
774
=head1 DESCRIPTION
775
 
776
This utility program is apart of the Package Release process. It is an interim solution.
777
 
778
The script is designed to be run as a cron jon on the dpkg_archive server.
779
 
780
It will scan the Release Manager database for packages that have been release, but do 
781
not yet have release notes. For each package it will then generate a Release Note by: 
782
 
783
=over 4
784
 
785
=item *
786
 
787
Invoke jats_get_releasenote_data to:
788
 
789
Extract relevent information from
790
 
791
=over 4
792
 
793
=item *
794
 
795
The Release Manager database
796
 
797
=item *
798
 
799
the ClearQuest database (now conatined within the Release Manager database)
800
 
801
=item *
802
 
803
the Jira Issue server 
804
 
805
=back
806
 
807
and create and XML file.
808
 
809
=item *
810
 
811
Invoke jats_gen_releasenote to:
812
 
813
=over 4
814
 
815
=item *
816
 
817
Process the the XML file created above, and package list info found within the new package. 
818
 
819
If no package informationis found then the utility will create a package list, but this is 
820
much slower than having it created by the package builder.
821
 
822
=item *
823
 
824
Create an XML file containing all the package information
825
 
826
=item *
827
 
828
Create an HTML based Release Note, from the XML file. This file could also be used to create a Release note in another format if required. 
829
 
830
=item *
831
 
832
Transfer these two files into the package in dpkg_archive
833
 
834
=item *
835
 
836
Insert the packages file list into the Release Manager database.
837
 
838
=back
839
 
840
=item *
841
 
842
Make the package read-only. This will trigger any post-install processing of the 
843
package. This is only required for packages that form a part of the build system.
844
 
845
=item *
846
 
847
Flag that the package has been released. This may tigger the BLAT package file transfer process 
848
and the package will be transferred to remote sites.
849
 
850
=item *
851
 
852
Determine the users that have registered interest in being informed when the package is released. 
853
It will then email these users.
854
 
855
=back
856
 
857
=head1 EXAMPLE
858
 
859
=head2 process_release_notes
860
 
861
This will perform a single scan of the Release Manager database and generate Release Notes as required.
862
 
863
=cut
864