Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
6914 dpurdie 1
package com.erggroup.buildtool.ripple;
2
 
7033 dpurdie 3
import org.slf4j.Logger;
4
import org.slf4j.LoggerFactory;
6914 dpurdie 5
 
6
import com.erggroup.buildtool.smtp.CreateUrls;
7
import com.erggroup.buildtool.smtp.Smtpsend;
8
 
9
import java.sql.SQLException;
10
import java.util.ArrayList;
11
import java.util.Iterator;
12
 
13
/**entity class holding build exclusion data
7080 dpurdie 14
 * 
15
 * There are three types of exclusion
16
 * Errors detected during planing. They may go away on the next plan
17
 *      These are 'hard' errors
18
 *          Have a rootCase string
19
 *          Have a null rootId
20
 *          
21
 * Build Errors
22
 *      These are persistent errors
23
 *          Have a null rootCause
24
 *          Have a null rootId
25
 *          Have a non-null root_file
26
 *          
27
 *  Indirect errors
28
 *      These are packages that depend on excluded packages
29
 *          Will have a non-null rootId          
30
 * 
6914 dpurdie 31
 */
32
public class BuildExclusion
33
{
34
  /**Logger
35
   * @attribute
36
   */
7033 dpurdie 37
  private static final Logger mLogger = LoggerFactory.getLogger(BuildExclusion.class);
6914 dpurdie 38
 
39
  /**The pvid of the package being excluded
40
   * @attribute
41
   */
7079 dpurdie 42
  public int mId;
6914 dpurdie 43
 
44
  /**root identifier is the PVID of the package that is causing the exclusion
45
   * A NULL value indicates that this entry(package) is the root cause of the of an exclusion
46
   * @attribute
47
   */
7079 dpurdie 48
  public int mRootId;
6914 dpurdie 49
 
50
  /**root cause
51
   * If not NULL, then this is the reason this package is being excluded
52
   * @attribute
53
   */
7079 dpurdie 54
  public String mRootCause;
6914 dpurdie 55
 
56
  /**test build instruction
57
   * @attribute
58
   */
59
  private int mTestBuildInstruction;
60
 
61
  /**Indicates that the item has been processed
62
   * @attribute
63
   */
64
  private boolean mProcessed = false;
7032 dpurdie 65
 
66
  /** Indicates that the entry was imported from the database
67
   *  Used to determine entries that are no-longer needed and can be removed from the database
68
   *  Really only applied to indirect exclusions where the reason for the exclusion no longer exists
69
   *  
70
   */
71
  private boolean mImported = false;
6914 dpurdie 72
 
73
  /**constructor
7032 dpurdie 74
   *    @param  identifier - pvid of the package being excluded
75
   *    @param  rootIdentifier  - pvid of the root package causing the exclusion. May be null
76
   *    @param  rootCause - Short (< 50 Char) string explaining the cause
77
   *    @param  testBuildInstruction - Indicates a text build instruction
6914 dpurdie 78
   */
79
  public BuildExclusion(int identifier, int rootIdentifier, String rootCause, int testBuildInstruction )
80
  {
81
    mLogger.debug("BuildExclusion");
82
    mId = identifier;
83
    mRootId = dealWithNullRootPvId(identifier, rootIdentifier);
84
    mRootCause = rootCause;
85
    mTestBuildInstruction = testBuildInstruction;
86
  }
87
 
88
  /**sets mProcessed true
89
   */
7032 dpurdie 90
  void setProcessed()
6914 dpurdie 91
  {
7033 dpurdie 92
    mLogger.debug("process {}", mId);
6914 dpurdie 93
    mProcessed = true;
94
  }
95
 
96
  /** @returns true if the item has been marked as processed. 
7032 dpurdie 97
   * Appears to be an indication that the entry has been superseded.
6914 dpurdie 98
   */
99
  boolean isProcessed()
100
  {
7033 dpurdie 101
    mLogger.debug("isProcessed {}", mId);
102
    mLogger.info("isProcessed returned {}", mProcessed);
6914 dpurdie 103
    return mProcessed;
104
  }
7032 dpurdie 105
 
106
  /** Flag as an imported entry
107
   *  Used to detect indirect exclusions that are no longer valid
108
   */
109
  void setImported()
110
  {
111
      mImported = true;
112
  }
6914 dpurdie 113
 
7032 dpurdie 114
  /** Test the state of the imported flag
115
   * 
116
   */
117
  boolean isImported()
118
  {
119
      return mImported;
120
  }
121
 
6914 dpurdie 122
  /**
123
   * Compare this item with parameters
124
   * @param identifier          - Related Package identifier
125
   * @param rootIdentifier      - Package identifier of root cause
126
   * @param  rootCause          - Root cause string. May be null
127
   * @return true if all attributes match
128
   */
129
  boolean compare( int identifier, int rootIdentifier, String rootCause)
130
  {
7033 dpurdie 131
    mLogger.debug("compare {}, {}, {}, {}", mId, identifier, rootIdentifier,  rootCause);
6914 dpurdie 132
    boolean retVal = false;
133
    rootIdentifier = dealWithNullRootPvId(identifier, rootIdentifier);
134
 
135
    if ( mRootCause == null )
136
    {
137
      if ( mId == identifier && mRootId == rootIdentifier && rootCause == null )
138
      {
139
        retVal = true;
140
      }
141
    }
142
    else
143
    {
144
      if ( mId == identifier && mRootId == rootIdentifier && mRootCause.compareTo(rootCause) == 0 )
145
      {
146
        retVal = true;
147
      }
148
    }
149
 
7033 dpurdie 150
    mLogger.info("compare returned {}", retVal);
6914 dpurdie 151
    return retVal;
152
  }
153
 
154
  /**
155
   * @param identifier  - identifier to match
156
   * @return true if mId attribute matches
157
   */
158
  boolean compare( int identifier )
159
  {
7033 dpurdie 160
    mLogger.debug("compare {},{}", mId,  identifier);
6914 dpurdie 161
    boolean retVal = false;
162
 
163
    if ( mId == identifier )
164
    {
165
      retVal = true;
166
    }
167
 
7033 dpurdie 168
    mLogger.info("compare returned {}", retVal);
6914 dpurdie 169
    return retVal;
170
  }
171
 
172
  /**runs exclude from build
173
   * Assumes that a connection to RM has been established
174
   * 
175
   * @param rm          Release Manager instance
7033 dpurdie 176
   * @param rtagId      Rtag Id we are working against
6914 dpurdie 177
   */
7033 dpurdie 178
  void excludeFromBuild( ReleaseManager rm, int rtagId ) throws SQLException, Exception
6914 dpurdie 179
  {
7033 dpurdie 180
    mLogger.debug("excludeFromBuild {}", mId);
6914 dpurdie 181
 
182
    // a null version and log file is passed to oracle
183
    // the planned version is only needed to remove a planned version from the planned version table
184
    // the ripple engine does not get this far ie it excludes pvs before claiming a version
185
    // this is the one instance where an existing build failure must be superseded in the database
186
    rm.excludeFromBuild(true, 
187
                        mId, 
188
                        null, 
7033 dpurdie 189
                        rtagId, 
6914 dpurdie 190
    		            mRootId == -1 ? null : String.valueOf(mRootId), 
191
    		            mRootCause, 
192
    		            null, 
193
    		            true, (mTestBuildInstruction > 0) );
194
  }
195
 
196
  /**runs include to build
197
   * Include a previously excluded package-version back into the build set
198
   * 
199
   * @param rm          Release Manager instance
7033 dpurdie 200
   * @param rtagId      Rtag Id we are working against
6914 dpurdie 201
   */
7033 dpurdie 202
  void includeToBuild( ReleaseManager rm, int rtagId ) throws SQLException, Exception
6914 dpurdie 203
  {
7033 dpurdie 204
    mLogger.debug("includeToBuild {}", mId);
205
    rm.includeToBuild(mId, rtagId);
6914 dpurdie 206
  }
207
 
208
  /**
209
   * Match this items id against that provided
210
   * @param id  - Id to match
211
   * @return true if id matches mId
212
   */
213
    private boolean isRelevant(int id)
214
    {
7033 dpurdie 215
      mLogger.debug("isRelevant {},{}", mId, id);
6914 dpurdie 216
      boolean retVal = false;
217
 
218
      if ( mId == id )
219
      {
220
        retVal = true;
221
      }
222
 
7033 dpurdie 223
      mLogger.info("isRelevant {},{}, returned {}",  mId,  id, retVal);
6914 dpurdie 224
      return retVal;
225
    }
226
 
227
  /**
228
   * Match this items mRootId against the id's provided in a collection
229
   * ie: Determine if any items in the collection are the root cause of this items
230
   * ie: Used to determine if an entry is for an indirectly excluded package where
231
   *     the root cause of the exclusion has been removed.
232
   *     
233
   * @param buildExclusionCollection - Collection to be processed
234
   * @return false: Indirectly excluded package whose root cause no longer exists
235
   */
236
  boolean isRelevant(ArrayList<BuildExclusion> buildExclusionCollection)
237
  {
7033 dpurdie 238
    mLogger.debug("isRelevant {}", mId);
6914 dpurdie 239
    boolean retVal = false;
240
 
241
    if ( mRootId == -1 )     {
242
      retVal = true;
243
 
244
    } else if(mRootId == -2 ) {
245
        // Excluded due to Ripple Stop
246
        // Will be recalculated so its not relevant
247
        retVal = false;
248
 
249
    } else {
7032 dpurdie 250
 
251
      retVal = false;
6914 dpurdie 252
      for (Iterator<BuildExclusion> it = buildExclusionCollection.iterator(); it.hasNext(); )
253
      {
254
        BuildExclusion buildExclusion = it.next();
255
 
256
        if ( buildExclusion.isRelevant( mRootId ) )
257
        {
258
          retVal = true;
259
          break;
260
        }
261
      }
262
    }
263
 
7033 dpurdie 264
    mLogger.info("isRelevant {} returned {}", mId, retVal);
6914 dpurdie 265
    return retVal;
266
  }
267
 
268
  /**
269
   * @return true if the root_pv_id is null (-1). This indicates that the item is the root case, and is not simply
270
   *         a by product of some other cause.
271
   */
272
  boolean isARootCause()
273
  {
7033 dpurdie 274
    mLogger.debug("isARootCause {}", mId);
6914 dpurdie 275
    boolean retVal = false;
276
 
277
    if ( mRootId == -1 )
278
    {
279
      retVal = true;
280
    }
281
 
7033 dpurdie 282
    mLogger.info("isARootCause {} returned {}",mId, retVal);
6914 dpurdie 283
    return retVal;
284
  }
285
 
286
  /**
287
   * Send an email notifying users about a build excluded package
288
   * It is user friendly, in that it does not trigger a storm of emails because a low level package 
289
   * has a build issue. It limits the emails to the low level package
290
   * 
291
   * i.e. only send email if the build exclusion has a null root pv id
292
   * and a non null root cause
293
   * 
294
   * @param    rippleEngine        - Ripple Engine Instance
295
   * @param    packageCollection   - Collection to process
296
   */
297
    public void email(RippleEngine rippleEngine, ArrayList<Package> packageCollection) throws SQLException, Exception
298
    {
7033 dpurdie 299
      mLogger.debug("email {}", mId);
6914 dpurdie 300
 
301
      //
302
      //    Only process entries that are direct failures of ripple engine detected failure
303
      //    Do not process entries that are indirectly excluded as this will cause an email storm
304
      //    Direct build failure: 
305
      //        Have no RootId and have a rootCause
306
      //
307
      if ( mRootId == -1 && mRootCause != null )
308
      {
309
        //  Locate the associated package entry
310
        Package pkg= rippleEngine.mReleaseManager.findPackage(mId, packageCollection);
311
 
312
        if ( pkg != ReleaseManager.NULL_PACKAGE )
313
        {
314
 
315
          // Is there anyone to send an email to
316
          String owners = pkg.emailInfoNonAntTask(rippleEngine);
317
 
318
          if ( owners != null )
319
          {
320
 
321
            String body =
322
            "Release: " + rippleEngine.mBaselineName + "<p>" +
323
            "Package: " + pkg.mName + "<p>" + 
324
            "Cause: "   + mRootCause + "<p>"+
325
            "RmRef: "   + CreateUrls.generateRmUrl(rippleEngine.getRtagId(), pkg.mId) +"<p>";
326
 
327
            try
328
            {
329
              Smtpsend.send(
7032 dpurdie 330
              rippleEngine.getMailServer(),             // mailServer
331
              rippleEngine.getMailSender(),             // source
6914 dpurdie 332
              owners,                                   // target
333
              null,                                     // cc
334
              null,                                     // bcc
335
              "BUILD FAILURE on package " + pkg.mName,  // subject
336
              body,                                     // body
337
              null                                      // attachment
338
              );
339
            }
340
            catch( Exception e )
341
            {
7033 dpurdie 342
                mLogger.info("email send exception. {}", e);
6914 dpurdie 343
            }
344
          }
345
 
346
          // Having sent the build failure email, complete a test build if applicable.
347
          // This ensures the test build instruction is not processed indefinitely
348
          // as there is no notion of excluding test builds
349
          pkg.completeTestBuild(rippleEngine, false);
350
        }
351
      }
352
    }
353
 
354
    /**
355
     * Hides how a rootPvId is treated
356
     * Only use rootPvId if not equal to the pvid
357
     * 
358
     * If the provided rootPvId matches the pvId, then the rootPvId will be set to null (-1)
359
     * This is to drive a direct build exclusion in the release manager
360
     * 
361
     * @param   pvid        - id
362
     * @param   rootPvId    - rootPvid
363
     * 
364
     * @returns rootPvId unless pvId matches= rootPvId, when it returns a null (-1)
365
    */
366
    private int dealWithNullRootPvId( int pvId, int rootPvId )
367
    {
368
      int retVal = rootPvId;
369
 
370
      if ( pvId == rootPvId )
371
      {
372
        retVal = -1;    // -1 == null entry
373
      }
374
 
375
      return retVal;
376
    }
377
 
378
    /**
379
     * Generate a single text line of info
380
     * Used within the UTF to 
381
     * @return String form of the state of the entry
382
     */
383
    public String info()
384
    {
385
        String rv = "";
386
        rv += "pvid=" + mId + ",RootId=" + mRootId + ",Processed=" + mProcessed + ",TestBuild=" + mTestBuildInstruction + ",RootCause=" + mRootCause;
7032 dpurdie 387
        if ( mImported ) {
388
            rv += ",Imported=" + mImported;
389
        }
6914 dpurdie 390
        return rv;
391
    }
392
}