Subversion Repositories DevTools

Rev

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