Subversion Repositories DevTools

Rev

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