Subversion Repositories DevTools

Rev

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