Subversion Repositories DevTools

Rev

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