framework changes for bootstrap b=352230 r=preed

This commit is contained in:
rhelmer%mozilla.com 2006-11-09 23:28:20 +00:00
Родитель 4b4a6b69ab
Коммит a53b6f184e
7 изменённых файлов: 189 добавлений и 82 удалений

Просмотреть файл

@ -5,11 +5,14 @@
package Bootstrap::Step; package Bootstrap::Step;
use MozBuild::Util; use MozBuild::Util;
use Config::General; use Config::General;
use POSIX qw(strftime);
my $DEFAULT_TIMEOUT = 3600;
# shared static config # shared static config
my $conf = new Config::General("bootstrap.cfg"); my $conf = new Config::General("bootstrap.cfg");
if (not $conf) { if (not $conf) {
die "Config is null: $!"; die "Config is null!";
} }
sub new { sub new {
@ -25,23 +28,32 @@ sub Shell {
my %args = @_; my %args = @_;
my $cmd = $args{'cmd'}; my $cmd = $args{'cmd'};
my $dir = $args{'dir'}; my $dir = $args{'dir'};
my $timeout = $args{'timeout'}; my $timeout = $args{'timeout'} ? $args{'timeout'} : $DEFAULT_TIMEOUT;
my $logFile = $args{'logFile'};
my $rv = ''; my $rv = '';
if ($dir) { if ($dir) {
chdir($dir) || die "Cannot chdir to $dir: $!"; $this->Log('msg' => 'Changing directory to ' . $dir);
chdir($dir) or die "Cannot chdir to $dir: $!";
$this->Log('msg' => 'Running shell command ' . $cmd . ' in dir ' . $dir); $this->Log('msg' => 'Running shell command ' . $cmd . ' in dir ' . $dir);
} else { } else {
$this->Log('msg' => 'Running shell command ' . $cmd); $this->Log('msg' => 'Running shell command ' . $cmd);
} }
$this->Log('msg' => 'Starting time is ' . $this->CurrentTime());
print "Timeout: $timeout\n";
if ($timeout) { if ($timeout) {
$rv = MozBuild::Util::RunShellCommand( $rv = MozBuild::Util::RunShellCommand(
'command' => "$cmd", 'command' => "$cmd",
'timeout' => "$timeout", 'timeout' => "$timeout",
'logfile' => "$logFile",
); );
} else { } else {
$rv = MozBuild::Util::RunShellCommand( $rv = MozBuild::Util::RunShellCommand(
'command' => "$cmd", 'command' => "$cmd",
'logfile' => "$logFile",
); );
} }
@ -49,28 +61,32 @@ sub Shell {
my $timedOut = $rv->{'timedOut'}; my $timedOut = $rv->{'timedOut'};
my $signalName = $rv->{'signalName'}; my $signalName = $rv->{'signalName'};
my $dumpedCore = $rv->{'dumpedCore'}; my $dumpedCore = $rv->{'dumpedCore'};
if ($exitValue) { my $pid = $rv->{'pid'};
if ($exitValue != 0) { print "Pid: $pid\n";
$this->Log('msg' => "output: $rv->{'output'}");
die("shell call returned bad exit code: $exitValue");
}
}
if ($timedOut) { if ($timedOut) {
$this->Log('msg' => "output: $rv->{'output'}"); $this->Log('msg' => "output: $rv->{'output'}") if $rv->{'output'};
die("FAIL shell call timed out after $timeout seconds"); die("FAIL shell call timed out after $timeout seconds");
} }
if ($signalName) { if ($signalName) {
$this->Log('msg' => "output: $rv->{'output'}");
print ("WARNING shell recieved signal $signalName"); print ("WARNING shell recieved signal $signalName");
} }
if ($dumpedCore) { if ($dumpedCore) {
$this->Log('msg' => "output: $rv->{'output'}"); $this->Log('msg' => "output: $rv->{'output'}") if $rv->{'output'};
die("FAIL shell call dumped core"); die("FAIL shell call dumped core");
} }
if ($exitValue) {
if ($exitValue != 0) {
$this->Log('msg' => "output: $rv->{'output'}") if $rv->{'output'};
die("shell call returned bad exit code: $exitValue");
}
}
if($rc->{'output'}) { if ($rv->{'output'} && not defined($logFile)) {
$this->Log('msg' => "output: $rv->{'output'}"); $this->Log('msg' => "output: $rv->{'output'}");
} }
# current time
$this->Log('msg' => 'Ending time is ' . $this->CurrentTime());
} }
sub Log { sub Log {
@ -89,8 +105,8 @@ sub Config {
my %config = $conf->getall(); my %config = $conf->getall();
if ($config{'app'}{'firefox'}{'release'}{'1.5.0.7'}{$var}) { if ($config{'app'}{$var}) {
return $config{'app'}{'firefox'}{'release'}{'1.5.0.7'}{$var}; return $config{'app'}{$var};
} else { } else {
die("No such config variable: $var\n"); die("No such config variable: $var\n");
} }
@ -105,30 +121,41 @@ sub CheckLog {
my $checkFor = $args{'checkFor'}; my $checkFor = $args{'checkFor'};
my $checkForOnly = $args{'checkForOnly'}; my $checkForOnly = $args{'checkForOnly'};
open (FILE, "< $log") || die "Cannot open file $log: $!"; if (not defined($log)) {
die "No log file specified";
}
open (FILE, "< $log") or die "Cannot open file $log: $!";
my @contents = <FILE>; my @contents = <FILE>;
close FILE || die "Cannot close file $log: $!"; close FILE or die "Cannot close file $log: $!";
if ($notAllowed) { if ($notAllowed) {
my @errors = grep(/$notAllowed/i, @contents); my @errors = grep(/$notAllowed/i, @contents);
if (@errors) { if (@errors) {
die "Errors in log ($log): \n\n @errors \n $!"; die "Errors in log ($log): \n\n @errors \n";
} }
} }
if ($checkFor) { if ($checkFor) {
if (not grep(/$checkFor/i, @contents)) { if (not grep(/$checkFor/i, @contents)) {
die "$checkFor is not present in file $log: $!"; die "$checkFor is not present in file $log \n";
} }
} }
if ($checkForOnly) { if ($checkForOnly) {
if (not grep(/$checkForOnly/i, @contents)) { if (not grep(/$checkForOnly/i, @contents)) {
die "$checkForOnly is not present in file $log: $!"; die "$checkForOnly is not present in file $log \n";
} }
my @errors = grep(!/$checkForOnly/i, @contents); my @errors = grep(!/$checkForOnly/i, @contents);
if (@errors) { if (@errors) {
die "Errors in log ($log): \n\n @errors \n $!"; die "Errors in log ($log): \n\n @errors \n";
} }
} }
} }
sub CurrentTime() {
my $this = shift;
my $args = @_;
return strftime("%T %D", localtime());
}
1; 1;

Просмотреть файл

@ -1,12 +1,12 @@
package MozBuild::Util; package MozBuild::Util;
use File::Path;
# Stolen from the code for bug 336463
my $EXEC_TIMEOUT = '600'; my $EXEC_TIMEOUT = '600';
sub RunShellCommand { sub RunShellCommand {
my %args = @_; my %args = @_;
my $shellCommand = $args{'command'}; my $shellCommand = $args{'command'};
my $logfile = $args{'logfile'};
# optional # optional
my $timeout = exists($args{'timeout'}) ? $args{'timeout'} : $EXEC_TIMEOUT; my $timeout = exists($args{'timeout'}) ? $args{'timeout'} : $EXEC_TIMEOUT;
@ -24,20 +24,31 @@ sub RunShellCommand {
my $dumpedCore; my $dumpedCore;
my $timedOut; my $timedOut;
my $output = ''; my $output = '';
my $pid;
eval { eval {
local $SIG{'ALRM'} = sub { die "alarm\n" }; local $SIG{'ALRM'} = sub { die "alarm\n" };
alarm $timeout; alarm $timeout;
if (! $redirectStderr || $shellCommand =~ "2>&1") { if (! $redirectStderr or $shellCommand =~ "2>&1") {
open CMD, "$shellCommand |" or die "Could not run command $shellCommand: $!"; $pid = open CMD, "$shellCommand |" or die "Could not run command $shellCommand: $!";
} else { } else {
open CMD, "$shellCommand 2>&1 |" or die "Could not close command $shellCommand: $!"; $pid = open CMD, "$shellCommand 2>&1 |" or die "Could not close command $shellCommand: $!";
} }
if (defined($logfile)) {
open(LOGFILE, ">> $logfile") or die "Could not open logfile $logfile: $!";
LOGFILE->autoflush(1);
}
while (<CMD>) { while (<CMD>) {
$output .= $_; $output .= $_;
print $_ if ($printOutputImmediately); print $_ if ($printOutputImmediately);
if (defined($logfile)) {
print LOGFILE $_;
}
}
if (defined($logfile)) {
close(LOGFILE) or die "Could not close logfile $logfile: $!";
} }
close CMD;# or die "Could not close command: $!"; close CMD;# or die "Could not close command: $!";
@ -51,13 +62,14 @@ sub RunShellCommand {
if ($@) { if ($@) {
if ($@ eq "alarm\n") { if ($@ eq "alarm\n") {
$timedOut = 1; $timedOut = 1;
kill(9, $pid) or die "Could not kill timed-out $pid: $!";
} else { } else {
warn "Error running $shellCommand: $@\n"; warn "Error running $shellCommand: $@\n";
$output = $@; $output = $@;
} }
} }
if ($exitValue || $timedOut || $dumpedCore || $signalNum) { if ($exitValue or $timedOut or $dumpedCore or $signalNum) {
if ($timedOut) { if ($timedOut) {
# callers expect exitValue to be non-zero if request timed out # callers expect exitValue to be non-zero if request timed out
$exitValue = 1; $exitValue = 1;
@ -68,7 +80,32 @@ sub RunShellCommand {
exitValue => $exitValue, exitValue => $exitValue,
sigName => $sigName, sigName => $sigName,
output => $output, output => $output,
dumpedCore => $dumpedCore }; dumpedCore => $dumpedCore,
pid => $pid,
};
}
## This is a wrapper function to get easy true/false return values from a
## mkpath()-like function. mkpath() *actually* returns the list of directories
## it created in the pursuit of your request, and keeps its actual success
## status in $@.
sub MkdirWithPath
{
my %args = @_;
my $dirToCreate = $args{'dir'};
my $printProgress = $args{'printProgress'};
my $dirMask = $args{'dirMask'};
die "ASSERT: MkdirWithPath() needs an arg" if not defined($dirToCreate);
## Defaults based on what mkpath does...
$printProgress = defined($printProgress) ? $printProgress : 0;
$dirMask = defined($dirMask) ? $dirMask : 0777;
eval { mkpath($dirToCreate, $printProgress, $dirMask) };
return defined($@);
} }
1; 1;

Просмотреть файл

@ -4,10 +4,33 @@ Bootstrap Release
Bootstrap is a release automation tool. Bootstrap is a release automation tool.
Use "release -h" for help. Use "release -h" for help.
Tools run first Pre-flight Checklist
----------------- -----------------
* checklist/config generator There are a number of manual steps that must be performed, so a default
* version bump tool end-to-end run will generally not work.
Before any steps:
* verify shipped-locales
* edit bootstrap.cfg
* edit tinder-config.pl/mozconfig
* version bump
After Build and Repack steps:
* rsync builds to candidates dir
After the Update step:
* edit patcher config
* edit mozilla/testing/release/updates/updates.cfg
After Sign step:
* create bouncer links
* rsync builds to mirrors
* wait 12 hours for mirrors to catch up
* rsync production AUS config
Steps are in dependency order. The process may be restarted at any step as Steps are in dependency order. The process may be restarted at any step as
long as all previous steps are satisfied. long as all previous steps are satisfied.
@ -16,53 +39,46 @@ PASS/FAIL verification is run after every step.
Steps Steps
----------------- -----------------
1) tag 1) Tag
2) build 2) Build
2.1) push 2.1) Push
2.2) announce 2.2) Announce
3) source 3) Source
4) repack 4) Repack
4.1) push 4.1) Push
4.2) announce 4.2) Announce
5) updates 5) Updates
5.1) push 5.1) Push
5.2) announce 5.2) Announce
6) stage 6) Stage
6.1) merge 6.1) Merge
6.2) announce 6.2) Announce
7) sign 7) Sign
8) release
8.1) announce
Details Details
----------------- -----------------
tag Tag
_RELEASE and _RCn for mozilla and talkback _RELEASE and _RCn for mozilla, l10n and talkback
build Build
en-US build from source (based on tag) en-US build from source (based on tag)
push to stage push to stage
announce announce
source Source
bz2 archive based on tag bz2 archive (based on tag)
push to stage push to stage
repack Repack
repack l10n, uses en-US build repack l10n, uses en-US build (based on tag)
push to stage push to stage
announce announce
updates Updates
uses patcher uses patcher
generate partials and AUS config ("snippets") generate partials and AUS config ("snippets")
push to stage push to stage
announce announce
stage Stage
uses groom-files uses groom-files
create release directory/filename structure create release directory/filename structure
merge updates merge updates
announce announce
sign Sign
manual manual
release
create bouncer links
rsync builds to mirrors
rsync production AUS config
announce

Просмотреть файл

@ -1,13 +1,23 @@
<app firefox> <app>
<release 1.5.0.7> productTag = FIREFOX_1_6_0_7
productTag = FIREFOX_1_5_0_7 branchTag = MOZILLA_1_8_0_BRANCH
branchTag = MOZILLA_1_8_0_7 pullDate = 2006-11-03 12:00 PDT
pullDate = 2006-09-06 18:00 PDT rc = 1
rc = 1 version = 1.6.0.7
version = 1.5.0.7 oldVersion = 1.5.0.7
appName = browser appName = browser
product = firefox product = firefox
buildDir = /builds/tinderbox/ buildDir = /builds/tinderbox/Fx-Mozilla1.8.0-Release
pushDate = 2006090601 l10n-buildDir = /builds/tinderbox/Fx-Mozilla1.8.0-l10n-Release
</release> pushDate = 2006-10-30-22
logDir = /builds/release/logs
mozillaCvsroot = /builds/cvsmirror/cvsroot
l10nCvsroot = /builds/cvsmirror/l10n
mofoCvsroot = /builds/cvsmirror/mofo
stageHome = /data/cltbld
updateDir = /builds/updates
verifyDir = /builds/verify
patcherConfig = moz180-branch-patcher2.cfg
tagDir = /builds/tags
buildPlatform = Linux_2.4.21-37.EL_Depend
</app> </app>

Просмотреть файл

@ -33,7 +33,7 @@ sub main {
sub ProcessArgs { sub ProcessArgs {
GetOptions( GetOptions(
\%config, \%config,
"step|s=s", "only|o=s", "list|l", "help|h", "step|s=s", "only|o=s", "list|l", "help|h", "execute|e", "verify|v",
); );
if ($config{'list'}) { if ($config{'list'}) {
@ -45,10 +45,12 @@ sub ProcessArgs {
} }
if ($config{'help'}) { if ($config{'help'}) {
print "Usage: release [-l] [-s Step] [-o Step] [-h]\n"; print "Usage: release [-l] [-s Step] [-o Step] [-e | v] [-h]\n";
print " -l list all Steps\n"; print " -l list all Steps\n";
print " -s start at Step\n"; print " -s start at Step\n";
print " -o only run one Step\n"; print " -o only run one Step\n";
print " -e only run Execute\n";
print " -v only run Verify\n";
print " -h this usage message\n"; print " -h this usage message\n";
exit(0); exit(0);
} }
@ -103,8 +105,16 @@ sub PerformStep {
print "Bootstrap running $stepName\n"; print "Bootstrap running $stepName\n";
my $step = "Bootstrap::Step::$stepName"->new(); my $step = "Bootstrap::Step::$stepName"->new();
eval { eval {
$step->Execute(); if (defined($config{'execute'})) {
$step->Verify(); print "Bootstrap only running Execute\n";
$step->Execute();
} elsif (defined($config{'verify'})) {
print "Bootstrap only running Verify\n";
$step->Verify();
} else {
$step->Execute();
$step->Verify();
}
}; };
if ($@) if ($@)
{ {

Просмотреть файл

@ -12,7 +12,7 @@ sub Execute {
} }
eval { eval {
$this->Shell( 'cmd' => 'true' ); $this->Shell( 'cmd' => 'true', logFile => 't/test.log' );
}; };
if ($@) { if ($@) {
@ -20,7 +20,7 @@ sub Execute {
} }
eval { eval {
$this->Shell( 'cmd' => 'false' ); $this->Shell( 'cmd' => 'false', logFile => 't/test.log' );
}; };
if (not $@) { if (not $@) {
@ -63,7 +63,7 @@ sub Execute {
sub Verify { sub Verify {
my $this = shift; my $this = shift;
$this->Shell('cmd' => 'echo Verify tag'); $this->Shell('cmd' => 'echo Verify tag', logFile => 't/test.log');
$this->Log('msg' => 'finished'); $this->Log('msg' => 'finished');
} }

Просмотреть файл

@ -2,3 +2,10 @@ success
failed failed
success success
failed failed
Verify tag
Verify tag
Verify tag
Verify tag
Verify tag
Verify tag
Verify tag