diff options
author | CamVan Nguyen <ctnguyen@us.ibm.com> | 2018-10-18 13:53:39 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2018-10-23 11:43:37 -0500 |
commit | c9d3c11613e9a47cf380b0cc60900eeb419d5e72 (patch) | |
tree | 796baf030b217a61c887a018efe46c3ee4bfff45 /src/build/tools | |
parent | 24f1a6c7c10b70339c61b29593247cce46416686 (diff) | |
download | talos-hostboot-c9d3c11613e9a47cf380b0cc60900eeb419d5e72.tar.gz talos-hostboot-c9d3c11613e9a47cf380b0cc60900eeb419d5e72.zip |
Remove auto-release & hbRelease tools
These tools have been ported to pfd_infra_tools
Change-Id: I5bc519689b8f13b48eb97a194b9b9f8ad0cb2840
RTC: 200487
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/67707
Reviewed-by: Sameer R Veer <sveer@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/build/tools')
-rwxr-xr-x | src/build/tools/hbRelease | 2983 |
1 files changed, 0 insertions, 2983 deletions
diff --git a/src/build/tools/hbRelease b/src/build/tools/hbRelease deleted file mode 100755 index 3c0e024ff..000000000 --- a/src/build/tools/hbRelease +++ /dev/null @@ -1,2983 +0,0 @@ -#!/usr/bin/perl -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/build/tools/hbRelease $ -# -# OpenPOWER HostBoot Project -# -# Contributors Listed Below - COPYRIGHT 2012,2018 -# [+] International Business Machines Corp. -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG - -use strict; - -use Getopt::Long qw(:config pass_through); -use POSIX; -use Text::Wrap; -use List::Util 'max'; -use Term::ReadKey; -use File::Temp qw/tempfile/; - -use Data::Dumper; - -my $debug = 0; -my $help = 0; - -my %globals = ( branch => "master", - component => "esw_hbfw", - cmvcUser => "hostboot", - email => "hostboot\@us.ibm.com" ); -# Token used by git-CI-tool @execute_discover, update there too -my $TOKEN = "!@#%^"; - -# List of files to check into CMVC separated by whitespace -my $CMVC_FILES = "src/hbfw/img/hostboot.bin ". - "src/hbfw/img/hostboot_extended.bin ". - "src/hbfw/img/hostboot_runtime.bin ". - "src/hbfw/img/makefile ". - "src/hbfw/fsp.tar ". - "src/hbfw/makefile ". - "src/hbfw/releaseNotes.html ". - "src/hbfw/simics.tar "; - - -if((defined $ENV{'FIPS_RELEASE'}) and - ($ENV{'FIPS_RELEASE'} =~ m/fips9/)) -{ - # Include all standalone images into the release as well - $CMVC_FILES .= "src/hbfw/nimbus/nimbus.pnor ". - "src/hbfw/nimbus/simics.tar ". - "src/hbfw/cumulus/cumulus.pnor ". - "src/hbfw/cumulus/simics.tar ". - "src/hbfw/cumulus_cdimm/cumulus_cdimm.pnor ". - "src/hbfw/cumulus_cdimm/simics.tar ". - "src/hbfw/axone/axone.pnor ". - "src/hbfw/axone/simics.tar "; -} - -# Directory to look up latest release tag for a specific release -my $HOSTBOOT_GSA_HOME = "/gsa/ausgsa/home/h/o/hostboot"; -my $LATEST_BUILD_DIR = "$HOSTBOOT_GSA_HOME/auto-hb-release/latest-builds"; - -GetOptions("debug!" => \$debug, - "help" => \$help, - "branch:s" => \$globals{"branch"}, - "component:s" => \$globals{"component"}, - "cmvcUser:s" => \$globals{"cmvcUser"}, - "email:s" => \$globals{"email"}); - -my %commands = ( "define" => \&execute_define, - "undef" => \&execute_undef, - "list-levels" => \&config_print_levels, - "query-gerrit" => \&execute_gerrit_query, - "query-git" => \&execute_git_query, - "query-level" => \&execute_level_query, - "add-patch" => \&execute_add_patch, - "add-forcedep" => \&execute_add_forcedep, - "verify-patches" => \&execute_verify_patches, - "release" => \&execute_release, - "publish-cq" => \&execute_publish_cq, - "build-name" => \&execute_build_name, - "fsp-ci" => \&execute_fsp_ci, - "gerrit-commit" => \&execute_gerrit_commit, - "pre-release" => \&execute_pre_release, - "post-release" => \&execute_post_release, - "create-track" => \&execute_create_track, - "checkinBuildToTrack" => \&execute_checkinBuildToTrack, - "help" => \&execute_help, - ); - -if ($help) -{ - execute_help(); -} - -my $command = shift @ARGV; -if ($commands{$command}) -{ - &{$commands{$command}}(); -} -else -{ - execute_help(); -} - -foreach my $arg (@ARGV) -{ - print "Unprocessed arg: $arg\n" if $debug; -} - -############################## Begin Actions ################################## - -sub execute_define -{ - print "Defining new level...\n"; - - my %level = (); - - GetOptions("level:s" => \$level{name}, - "name:s" => \$level{name}, - "baseline:s" => \$level{base}, - "released:s" => \$level{released}); - - die "Missing level name" if ($level{name} eq ""); - die "Missing baseline name" if ($level{base} eq ""); - die "Missing released level name" if ($level{released} eq ""); - - print "New level: ".$level{name}.":".$level{base}.":".$level{released}."\n" - if $debug; - - $level{base} = git_resolve_ref($level{base}); - $level{released} = git_resolve_ref($level{released}); - - config_add_level(\%level); -} - -sub execute_undef -{ - my $level = shift @ARGV; - - die "Level to undefine not given" if ($level eq ""); - - my $levels = config_list_levels(); - die "Level $level does not exist" if (not defined $levels->{$level}); - - print "Undefining level $level...\n"; - config_del_level($level); -} - -sub execute_gerrit_query -{ - my $project = ""; - - GetOptions("project:s" => \$project); - - if ("" eq $project) - { - $project = config_project(); - } - - my $items = gerrit_query("status:open project:$project ". - "branch:".$globals{"branch"}); - - foreach my $item (@$items) - { - if (defined $item->{"project"}) - { - print wrap("","",$item->{"subject"}) . "\n"; - print "\t" . $item->{"id"} . "\n"; - print "\n"; - } - } -} - -sub execute_git_query -{ - my $level = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level); - - die "Missing level name" if ($level eq ""); - - $globals{"branch"} = git_resolve_ref($globals{"branch"}); - - my $level = config_get_level($level); - - my $commits = git_commit_history($globals{"branch"}, $level->{base}); - - foreach my $commit (@{$commits}) - { - my $subject = git_get_subject($commit); - print "$subject\n\t$commit\n\n"; - } -} - -sub execute_level_query -{ - my $level = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level); - - die "Missing level name" if ($level eq ""); - - my $level_info = config_get_level($level); - - print "Level $level\n"; - print " Base: \n"; - print " ".git_name_rev($level_info->{base})."\n"; - print " Released:\n"; - print " ".git_name_rev($level_info->{released})."\n"; - if ($globals{"branch"} ne "master") - { - print " Branch:\n"; - print " ".$globals{"branch"}."\n"; - } - print " Patches:\n"; - foreach my $patch (sort @{$level_info->{patches}}) - { - print " $patch\n"; - } - print " Forced Deps:\n"; - foreach my $dep (sort keys %{$level_info->{forceDeps}}) - { - my $deps = $level_info->{forceDeps}; - print " $dep =>\n"; - print " ".$deps->{$dep}."\n"; - } -} - - -sub execute_add_patch -{ - my $level = ""; - my $patch = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level, - "patch:s" => \$patch); - - die "Missing level name" if ($level eq ""); - die "Missing patch name" if ($patch eq ""); - - config_add_patch($level, $patch); -} - -sub execute_add_forcedep -{ - my $level = ""; - my $from = ""; - my $to = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level, - "from:s" => \$from, - "to:s" => \$to); - - die "Missing level name" if ($level eq ""); - die "Missing from depend" if ($from eq ""); - die "Missing to depend" if ($to eq ""); - - config_add_dep($level, $from, $to); -} - -sub execute_verify_patches -{ - my $level = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level); - - die "Missing level name" if ($level eq ""); - - my $level_info = config_get_level($level); - my $patches = $level_info->{patches}; - - $patches = gerrit_resolve_patches($patches); - - config_verify_patches($level_info->{base}, $patches); -} - -sub execute_release -{ - my $level = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level); - - die "Missing level name" if ($level eq ""); - - my $level_info = config_get_level($level); - - config_release($level_info,1); -} - -sub execute_publish_cq -{ - my $level = ""; - my $track = ""; - my $released = ""; - - GetOptions("name:s" => \$level, - "level:s" => \$level, - "track:s" => \$track, - "released:s" => \$released); - - die "Missing level name" if ($level eq ""); - die "Missing track" if ($track eq ""); - - my $level_info = config_get_level($level); - - $released = $level_info->{released} if ($released eq ""); - - publish_cq($level, $track, $released); -} - -sub execute_build_name -{ - my $release = "840"; - my $build_letter = "a"; - - GetOptions("release:s" => \$release, - "letter:s" => \$build_letter); - - system ("date +hb%m%d".$build_letter."_%g%V.$release"); -} - -sub execute_fsp_ci -{ - - my $patches = ""; - my $discover = 0; - my %level = (); - my $branch = $globals{"branch"}; - my $bbuild_hbRel = ""; - - GetOptions("level:s" => \$level{name}, - "patches:s" => \$patches, - "discover" => \$discover, - "basestr:s" => \$level{base}, - "bbuild-hbRel:s" => \$bbuild_hbRel); - - die "Missing level name" if ($level{name} eq ""); - die "Missing level base" if ($level{base} eq ""); - die "Missing patches" if ($patches eq ""); - die "Missing bbuild's hostboot release" if ($bbuild_hbRel eq ""); - - print "Creating Hostboot CI release...\n" if !$discover; - - # Parse out csv list of patches - my @patches = split(/,+/, $patches); - - print ">>>Patches\n" if $debug; - print Dumper @patches if $debug; - print "<<<End of Patches\n" if $debug; - - # Define release - print "Basestr: " if $debug; - $level{base} = git_resolve_ref($level{base}); - $level{released} = $level{base}; - config_add_level(\%level); - - # Get all commits between level base and the bbuilds hb release - my @commits = split('\n',`git rev-list $level{base} ^$bbuild_hbRel`); - # Check all commits between gerrit/<branch> and bbuild's hbRel for any - # cmvc req's that are needed in the discover step only. - if ($discover) - { - # Check each commit message for CMVC reqs - foreach my $commit (@commits) - { - my @msg_lines = split('\n',git_commit_msg($commit)); - # Search commit message for dependencies - foreach my $line (@msg_lines) - { - # Print out CMVC dependencies - if ($line =~ m/cmvc-([a-zA-Z]+):/i) - { - print "$TOKEN Need ".$line."\n"; - } - } - } - } - # Print out commits that are in the gerrit branch and not the bbuild hbRel - else - { - print "\n========\n"; - print "Commits in gerrit/$branch but not in bbuild => $bbuild_hbRel\n\n"; - print "**Note these commits may cause problems too, but since they\n"; - print " are merged commits, they should have passed fsp-ci prior.\n"; - print " It is done this way to greatly simply dependencies of your\n"; - print " commit ontop of a hostboot release\n\n"; - my $i=1; - foreach my $commit (@commits) - { - print " $i. $commit\n"; - $i++; - } - print "\n"; - } - - # Resolve level dependencies - config_resolve_level_dep($level{name}, $level{base}, @patches); - - if(!$discover) - { - # Create hb release - my $level_info = config_get_level($level{name}); - config_release($level_info,0); - } -} - -sub execute_pre_release -{ - my $release = ""; - my $level = ""; - my $checkInDir = ""; - my $released = ""; - my $track = ""; - # - #Pass $cmvcCheckinForceFlag from Jenkins to check in files w/ '-force' option - #within CMVC to break the file links - - my $cmvcCheckinForceFlag = ""; - - if ( $ENV{CMVC_CHECKIN_FORCEFLAG} eq "-force" ) - { - $cmvcCheckinForceFlag = "$ENV{CMVC_CHECKIN_FORCEFLAG}"; - } - - GetOptions("release:s" => \$release); - GetOptions("level:s" => \$level); - GetOptions("checkInDir:s" => \$checkInDir); - GetOptions("released:s" => \$released); - GetOptions("track:s" => \$track); - - die "Missing release" if ($release eq ""); - die "Missing level" if ($level eq ""); - die "Missing check in directory" if ($checkInDir eq ""); - die "Missing released" if ($released eq ""); - - if($release =~ m/fips9/) - { - $CMVC_FILES .= "src/hbfw/img/hostboot_bootloader.bin "; - $CMVC_FILES .= "src/hbfw/img/hostboot_securerom.bin "; - } - - - my $feature = ""; - if($track eq "") - { - # CMVC open feature - my $open_feature = "Feature -open -component $globals{component}"; - $open_feature .= " -remarks \"Hostboot Release - $level\" -verbose"; - # Get the Feature number from the output, should be the only numbers. - $feature = run_system_command($open_feature); - $feature =~ s/[^0-9]//g; - - # CMVC assign feature - run_system_command("Feature -assign $feature -owner $globals{cmvcUser} -verbose"); - - # CMVC accept feature - run_system_command("Feature -accept $feature -verbose"); - - # CMVC create track - run_system_command("Track -create -release $release -feature $feature -verbose"); - } - else - { - $feature = $track; - } - - # Add in cmvc coReqs and cmvc preReqs - execute_cmvc_reqs($feature,$level,$released,$release); - - #Lock Files - run_system_command("File -lock $CMVC_FILES -release $release -feature $feature -verbose"); - - #Check In Files - chdir ($checkInDir); - run_system_command("File -checkin $CMVC_FILES -top $checkInDir -release $release -feature $feature -verbose $cmvcCheckinForceFlag"); - - my $featureFile = $ENV{CMVC_FEATURE_FILE}; - open(CMVC_FEATURE,">",$featureFile) - or die("Cannot open: $featureFile: $!"); - print CMVC_FEATURE "FEATURE=$feature"; - close(CMVC_FEATURE); - - #Complete Fix Records - run_system_command("Fix -complete -feature $feature -release $release -component esw_hbfw -verbose"); - - #Integrate the track - run_system_command("Track -integrate -feature $feature -release $release -verbose"); - - #Get ClearQuest ID - my $response = run_system_command("Feature -view $feature"); - my ($cq_id) = $response =~ /CQID\s+(.*)/; - print $cq_id if $debug; - - #Print out Debug information - print_debug_info($level, $feature, $cq_id, $released); -} - -sub execute_create_track -{ - my $level = ""; - my $release = ""; - my $released = ""; - my $track = ""; - - GetOptions("level:s" => \$level); - GetOptions("release:s" => \$release); - GetOptions("released:s" => \$released); - GetOptions("track:s" => \$track); - - die "Missing level" if ($level eq ""); - die "Missing release" if ($release eq ""); - die "Missing released" if ($released eq ""); - - # - my $feature = ""; - my $rel_needs_appr = ""; - my $approval_flag = "yes"; - - if($track eq "") - { - # CMVC open feature - my $open_feature = "Feature -open -component $globals{component}"; - $open_feature .= " -remarks \"Hostboot Release - $level\" -verbose"; - # Get the Feature number from the output, should be the only numbers. - print "open_feature=> $open_feature\n"; - $feature = run_system_command($open_feature); - $feature =~ s/[^0-9]//g; - # - print "\n\n--------------------------------------\n"; - print "level (passed as \"RELEASE_NAME\") => $level\n"; - print "release (passed as \"FIPS_RELEASE\") => $release\n"; - print "released (passed as \"PREVIOUS_RELEASE\") => $released\n"; - print "owner=> $globals{cmvcUser}\n"; - print "feature=> $feature\n\n"; - print "\n--------------------------------------\n\n"; - - # CMVC assign feature - print "#####-> run_system_command(\"Feature -assign $feature -owner $globals{cmvcUser} -verbose\")\n"; - run_system_command("Feature -assign $feature -owner $globals{cmvcUser} -verbose"); - - # CMVC accept feature - print "#####-> run_system_command(\"Feature -accept $feature -verbose\");\n"; - run_system_command("Feature -accept $feature -verbose"); - - # CMVC create track - print "#####-> run_system_command(\"Track -create -release $release -feature $feature -verbose\")\n"; - run_system_command("Track -create -release $release -feature $feature -verbose"); - - # CMVC check track - print "#####-> $rel_needs_appr = run_system_command(\"Report -g ReleaseView -where \"name='$release'\" -select approve\")\n"; - chomp($rel_needs_appr = run_system_command("Report -g ReleaseView -where \"name='$release'\" -select approve")); - print "\nrel_needs_appr=> \"$rel_needs_appr\"\n"; - print "\napproval_flag=> \"$approval_flag\"\n"; - } - else - { - $feature = $track; - } - # - my $featureFile = $ENV{CMVC_FEATURE_FILE}; - open(CMVC_FEATURE,">",$featureFile) - or die("Cannot open: $featureFile: $!"); - print CMVC_FEATURE "FEATURE=$feature"; - close(CMVC_FEATURE); - - my $rel_needs_appr_file = $ENV{REL_NEEDS_APPR_FILE}; - open(REL_NEEDS_APPR,">",$rel_needs_appr_file) - or die("Cannot open: $rel_needs_appr_file: $!"); - print REL_NEEDS_APPR "REL_NEEDS_APPR=$rel_needs_appr"; - close(REL_NEEDS_APPR); - - my $notify_email_file = $ENV{'NOTIFY_EMAIL_FILE'}; - open(NOTIFY_EMAIL_TXT,">",$notify_email_file) - or die("Cannot open: $notify_email_file: $!"); - - chomp(my $datenow = run_system_command("date")); - # - open(TXTRELNOTE, "< ", $ENV{'RELEASENOTESTXT'}); - my $txtrelnote = <TXTRELNOTE>; - close(TXTRELNOTE); - # - my $NEXTJOB=\ - "https://hostboot-jenkins.swg-devops.com/job/Hostboot/job/Release/job/\ - auto-release-HB/job/rel-fips/job/rel-fips-4-checkinBuildToTrack/\ - build?delay=0sec"; - if($rel_needs_appr eq $approval_flag) - { - print "(in IF loop)\nYes, found \$rel_needs_appr eq \$approval_flag: ($rel_needs_appr eq $approval_flag)\n"; - print "MUSTFIX_APPROVERS=> $ENV{'MUSTFIX_APPROVERS'}\n"; - print "RELEASE_ADMINS=> $ENV{'RELEASE_ADMINS'}\n"; - my $MAIL_SUB = "Action Required: Your approval required for Track \ - $ENV{'FIPS_RELEASE'}:$feature"; - print NOTIFY_EMAIL_TXT "[$datenow]\n\n\nDear Approver(s) [$ENV{MUSTFIX_APPROVERS}],\n\tThere is a new track/feature opened pending your approval for a mustfix release.\n\tDetails are below, please approve it ASAP, thanks!\n"; - print NOTIFY_EMAIL_TXT "\n\t(Note: Jenkins job will time-out if approval not obtained within a day of receiving this notice)\n\n"; - print NOTIFY_EMAIL_TXT "\tFIPS_RELEASE=$ENV{FIPS_RELEASE}\n\tFEATURE=$feature\n"; - print NOTIFY_EMAIL_TXT "\n\n$txtrelnote\n\n"; - print NOTIFY_EMAIL_TXT "#--------------------------#"; - print NOTIFY_EMAIL_TXT "\n\n\nDear Release_admin(s) [$ENV{'RELEASE_ADMINS'}],\n\tOnce this track is approved, please use following information if/as required to \tretrigger the release job (e.g. if it had timed out beyond the wait-time of 1 day):\n\n"; - print NOTIFY_EMAIL_TXT "\n\tNEXTJOB=$NEXTJOB"; - print NOTIFY_EMAIL_TXT "\n\tREL_FIPS_TRIGGER_PROJ=$ENV{REL_FIPS_TRIGGER_PROJ}\n\tREL_FIPS_TRIGGER_BUILD_NUM=$ENV{REL_FIPS_TRIGGER_BUILD_NUM}\n"; - print NOTIFY_EMAIL_TXT "\n\n\n(A copy of this email has been sent to:\n\t$ENV{'MUSTFIX_APPROVERS'}\n\t$ENV{'RELEASE_ADMINS'}\n\t)\n\n\n"; - print NOTIFY_EMAIL_TXT "#-----------<E-O-F>---------------#\n"; - close(NOTIFY_EMAIL_TXT); - run_system_command("cat $notify_email_file | mail -s \"$MAIL_SUB\" $ENV{'MUSTFIX_APPROVERS'} $ENV{'RELEASE_ADMINS'}"); - } - else - { - - print "(in ELSE loop)\nSorry, \$rel_needs_appr ne \$approval_flag: ($rel_needs_appr ne $approval_flag)\n"; - print NOTIFY_EMAIL_TXT "#--------------------------#\n"; - print NOTIFY_EMAIL_TXT "[$datenow]\n\n\nNo approval required for:\nFIPS_RELEASE=$ENV{FIPS_RELEASE}\nFEATURE=$feature\n"; - print NOTIFY_EMAIL_TXT "\n\n$txtrelnote\n\n"; - print NOTIFY_EMAIL_TXT "\nNEXTJOB=$NEXTJOB"; - print NOTIFY_EMAIL_TXT "\nREL_FIPS_TRIGGER_PROJ=$ENV{REL_FIPS_TRIGGER_PROJ}\nREL_FIPS_TRIGGER_BUILD_NUM=$ENV{REL_FIPS_TRIGGER_BUILD_NUM}\n\n"; - print NOTIFY_EMAIL_TXT "\n\n(Since, no approval required, no email or other notification sent out)\n\n"; - print NOTIFY_EMAIL_TXT "#-----------<E-O-F>---------------#\n"; - close(NOTIFY_EMAIL_TXT); - } - - # Add in cmvc coReqs and cmvc preReqs - print "#####-> execute_cmvc_reqs($feature,$level,$released,$release)\n"; - execute_cmvc_reqs($feature,$level,$released,$release); -} - -sub execute_checkinBuildToTrack -{ - my $level = ""; - my $release = ""; - my $checkInDir = ""; - my $released = ""; - # - #Pass $cmvcCheckinForceFlag from Jenkins to check in files w/ '-force' option - #within CMVC to break the file links - - my $cmvcCheckinForceFlag = ""; - - if ( $ENV{CMVC_CHECKIN_FORCEFLAG} eq "-force" ) - { - $cmvcCheckinForceFlag = "$ENV{CMVC_CHECKIN_FORCEFLAG}"; - } - - GetOptions("level:s" => \$level); - GetOptions("release:s" => \$release); - GetOptions("checkInDir:s" => \$checkInDir); - GetOptions("released:s" => \$released); - - die "Missing level" if ($level eq ""); - die "Missing release" if ($release eq ""); - die "Missing check in directory" if ($checkInDir eq ""); - die "Missing released" if ($released eq ""); - - my $featureFile = $ENV{CMVC_FEATURE_FILE}; - open(CMVC_FEATURE,"<",$featureFile) - or die("Cannot open: $featureFile: $!"); - #Read the feature from the file: - my $keyval = <CMVC_FEATURE>; - my ($key, $feature) = split /=/, $keyval ; - close(CMVC_FEATURE); - - if($release =~ m/fips9/) - { - $CMVC_FILES .= "src/hbfw/img/hostboot_bootloader.bin "; - $CMVC_FILES .= "src/hbfw/img/hostboot_securerom.bin "; - } - - print "\n\n--------------------------------------\n"; - print "level (passed as \"RELEASE_NAME\") => $level\n"; - print "release (passed as \"FIPS_RELEASE\") => $release\n"; - print "checkInDir (passed as \"CMVC_DIR\") => $checkInDir\n"; - print "released (passed as \"PREVIOUS_RELEASE\") => $released\n"; - print "feature (read from the \"$ENV{CMVC_FEATURE_FILE}\" file => $feature\n"; - print "CMVC_FILES => $CMVC_FILES\n"; - print "\n--------------------------------------\n\n"; - - #Lock Files - print "#####-> run_system_command(\"File -lock $CMVC_FILES -release $release -feature $feature -verbose\")\n"; - run_system_command("File -lock $CMVC_FILES -release $release -feature $feature -verbose"); - #Check In Files - print "Present working directory:\n"; - run_system_command("pwd"); - print "Switching directory to \"$checkInDir\" .....\n"; - chdir ($checkInDir); - run_system_command("pwd"); - print "#####-> run_system_command(\"File -checkin $CMVC_FILES -top $checkInDir -release $release -feature $feature -verbose $cmvcCheckinForceFlag\")\n"; - run_system_command("File -checkin $CMVC_FILES -top $checkInDir -release $release -feature $feature -verbose $cmvcCheckinForceFlag"); - - #Complete Fix Records - print "#####-> run_system_command(\"Fix -complete -feature $feature -release $release -component esw_hbfw -verbose\")\n"; - run_system_command("Fix -complete -feature $feature -release $release -component esw_hbfw -verbose"); - - #Integrate the track - run_system_command("Track -integrate -feature $feature -release $release -verbose"); - - #Get ClearQuest ID - my $response = run_system_command("Feature -view $feature"); - my ($cq_id) = $response =~ /CQID\s+(.*)/; - print $cq_id if $debug; - - #Print out Debug information - print_debug_info($level, $feature, $cq_id, $released); -} - -sub execute_post_release -{ - my $feature = ""; - my $release = ""; - my $level = ""; - my $released = ""; - - GetOptions("feature:s" => \$feature); - GetOptions("release:s" => \$release); - GetOptions("level:s" => \$level); - GetOptions("released:s" => \$released); - - die "Missing feature" if ($feature eq ""); - die "Missing release" if ($release eq ""); - die "Missing level" if ($level eq ""); - die "Missing released" if ($released eq ""); - - #Check for HW image coreq and prereq - hw_req_check($level, $released); - - #Get ClearQuest ID - my $response = run_system_command("Feature -view $feature"); - my ($cq_id) = $response =~ /CQID\s+(.*)/; - print $cq_id if $debug; - - # Fetch level and Publish release notes to CQ - chdir($ENV{HOSTBOOT_WORKSPACE}); - run_system_command("git fetch gerrit refs/tags/$level"); - run_system_command("git checkout FETCH_HEAD"); - publish_cq($level, $cq_id, $released); - print_debug_info($level, $feature, $cq_id, $released); -} - -sub execute_gerrit_commit -{ - my $patches = ""; - - GetOptions("patches:s" => \$patches); - - die "Missing patches" if ($patches eq ""); - - # Parse out csv list of patches - my @patches = split(/,+/, $patches); - - my $commits = gerrit_resolve_patchset(\@patches); - foreach my $commit (@$commits) - { - print $commit; - print "," if( \$commit != \$commits->[-1] ) - } - print "\n"; -} - -sub execute_help -{ - my $command = shift @ARGV; - - if ($command eq "") - { - print "hbRelease:\n"; - print " Prepare the hostboot codebase for release.\n"; - print "\n"; - print " Syntax:\n"; - print " hbRelease [options] <tool>\n"; - print "\n"; - print " Available subtools:\n"; - foreach my $key (sort keys %commands) - { - print " $key\n"; - } - print "\n"; - print " Global options:\n"; - print " --debug Enable debug mode.\n"; - print " --help Display help on a specific tool.\n"; - print " --branch Branch to use for release.\n"; - print "\n"; - print " Note: Generally a <commit> can be any git or gerrit\n"; - print " reference. A git commit number, tag, branch, or\n"; - print " a gerrit change-id are all valid.\n"; - } - elsif (not defined $commands{$command}) - { - die "Unknown subcommand: $command.\n"; - } - else - { - my %help = ( - "define" => -q( - Define a new level for release. - - Options: - --level=<name> Name for the new level [required]. - --base=<commit> Baseline commit [required]. - --released=<commit> Commit of previous release [required]. -), - "undef" => -q( - Delete a previously defined release level. - - Options: - --level=<name> Name for the level to delete [required]. -), - "list-levels" => -q( - Displays a list of currently defined levels. -), - - "query-gerrit" => -q( - Displays a list of open change-sets from the Gerrit server. -), - "query-git" => -q( - Displays a list of merged commits which are NOT currently destined - for a release level. - - Options: - --level=<name> Name for the level to query [required]. - --branch=<commit> Branch to query against [default=master]. -), - "query-level" => -q( - Displays information about a defined release level. - - Options: - --level=<name> Name for the level to query [required]. -), - "add-patch" => -q( - Adds a commit to the patch-list for a release. - - Options: - --level=<name> Release to add patch to [required]. - --patch=<commit> Commit to add to patch-list [required]. -), - "add-forcedep" => -q( - Add a commit-pair as a forced dependency for a release. - - Options: - --level=<name> Release to add dependency to [required]. - --from=<commit> Decendent commit in the dependency [required]. - --to=<commit> Ancestor commit in the dependency [required]. -), - "verify-patches" => -q( - Verify patch-list to ensure all dependencies are met. - - This tool will give a list of dependency candidates if an ancestor - commit is found modifying the same files as a commit in the - patch-list. - - Options: - --level=<name> The level to verify [required]. -), - "release" => -q( - Create a branch / tag based on the definition of a release. - - Options: - --level=<name> The level to release [required]. -), - "publish-cq" => -q( - Update CQ tracks for any released commits to indicate which Hostboot - build the commit was added to and which CQ track was used to add the - HB release to CMVC. - - Options: - --level=<name> The level to publish [required]. - --track=<name> The CQ number used release [required]. - --released=<commit> Alternate starting point for publish [optional]. -), - "build-name" => -q( - Display a properly formatted build name based on the date. - - Ex: hb0402a_1412.810 - - Options: - --release=<id> Release name [default=810]. - --letter=[a-z] Build letter [default=a]. -), - "fsp-ci" => -q( - Creates a hb release based on a list of patches - - Options: - --level=<name> The level to create [required]. - --patches=<csv> CSV of patches to add [required]. - --branch=[a-z] Branch to use for release [default=master]. -), - "gerrit-commit" => -q( - Get commit number of gerrit change-id, patch-set pairs - - Options: - --patches=<change-id:patchset> CSV of change-id:patchset [required]. -), - "pre-release" => -q( - This is used by the auto-release process and handles HostBoot release - steps required before FSP-CI is run. Steps include CMVC feature create - through file checkin - - Options: - --level=<name> The hostboot release tag name [required]. - --release=<name> Fips release (e.g fips860) [required]. - --checkInDir=<name> Top level CMVC checkout directory path [required]. -), - "post-release" => -q( - This is used by the auto-release process and handles HostBoot release - steps required after FSP-CI has passed. Steps include CMVC complete, - integrat and publishing releast notes to CQ - - Options: - --level=<name> The hostboot release tag name [required]. - --release=<name> Fips release (e.g fips860) [required]. - --feature=<number> CMVC feature associated with release [required]. -), - ); - - my $release = ""; - my $level = ""; - my $checkInDir = ""; - - print "hbRelease $command:"; - print $help{$command}; - - } -} - - -######################### Begin Utility Subroutines ########################### - - - -# sub create_release_notes -# -# Generates an HTML file (releaseNotes.html) with the release notes for a -# release. -# -# @param [in] level - The level name to release. -# @param [in] level_info - The level_info hash (see config_get_level). -# -sub create_release_notes -{ - my $level = shift; - my $level_info = shift; - - my $commits = git_commit_history("HEAD", $level_info->{released}); - - open RELNOTE, "> ".git_root()."/releaseNotes.html"; - open TXTRELNOTE, "> ".$ENV{'RELEASENOTESTXT'}; - print TXTRELNOTE "The list of commits included for approval are:\n"; - print RELNOTE "<html>\n"; - print RELNOTE " <head><title>Release notes for $level</title></head>\n"; - print RELNOTE <<STYLESHEET; - <style type="text/css"> - table.release { - border-width: 1px; - border-spacing: 2px; - border-style: outset; - border-color: gray; - border-collapse: separate; - background-color: white; - } - table.release th { - border-width: 1px; - padding: 1px; - border-style: inset; - border-color: gray; - background-color: white; - } - table.release td { - border-width: 1px; - padding: 1px; - border-style: inset; - border-color: gray; - background-color: white; - } - </style> -STYLESHEET - print RELNOTE " <body>\n"; - - print RELNOTE "<h1>Level: $level</h1>\n"; - print RELNOTE "<h2>Included commits:</h2>\n"; - print RELNOTE "<table class='release'>\n"; - print RELNOTE " <tr>\n"; - print RELNOTE " <th>RTC/CQ Number(s)</th>\n"; - print RELNOTE " <th>Subject</th>\n"; - print RELNOTE " <th>Git Commit</th>\n"; - print RELNOTE " </tr>\n"; - - - foreach my $commit (@{$commits}) - { - my $subject = git_get_subject($commit); - my $rtc = rtc_workitem_num($commit); - my $rtc_hyper = ""; - my $cq = cq_workitem_num($commit); - my $cq_hyper = ""; - - if ($rtc ne "") - { - $rtc_hyper = rtc_hyperlink($rtc); - $rtc_hyper = "<a href='$rtc_hyper' target='_blank'>$rtc</a>"; - } - if ($cq ne "") - { - $cq_hyper = cq_hyperlink($cq); - $cq_hyper = "<a href='$cq_hyper' target='_blank'>$cq</a>"; - - if ($rtc_hyper ne "") - { - $cq_hyper = "<br>$cq_hyper"; - } - } - - print RELNOTE " <tr>\n"; - print RELNOTE " <td>$rtc_hyper $cq_hyper</td>\n"; - print RELNOTE " <td>$subject</td>\n"; - print RELNOTE " <td>$commit</td>\n"; - print RELNOTE " </tr>\n"; - print TXTRELNOTE "$commit\n"; - } - print RELNOTE "</table>\n"; - - print RELNOTE " </body>\n"; - print RELNOTE "</html>\n"; - - close RELNOTE; - close TXTRELNOTE; - - system "git add ".git_root()."/releaseNotes.html"; - #system "git add ".git_root()."/releaseNotes.txt"; - system "git commit -m \"Release notes for $level\""; - -} - -# sub git_resolve_ref -# -# Transforms a symbolic git reference into a commit number. -# -# @param [in] ref - The reference to resolve. -# -# @return string - Resolved git commit number. -# -sub git_resolve_ref -{ - my $ref = shift; - my $resolve = ""; - - if (gerrit_is_patch($ref)) - { - my $gerrit = gerrit_resolve_patches([$ref]); - $resolve = @{$gerrit}[0]; - } - else - { - open COMMAND, "git log -n1 --pretty=\"%H\" $ref |"; - $resolve = <COMMAND>; - close COMMAND; - chomp $resolve; - } - - die "Unable to resolve ref $ref" if ($resolve eq ""); - print "Resolved $ref as $resolve\n" if $debug; - - return $resolve; -} - -# sub git_root -# -# Determines the path of the root of the git repository. -# -# @return string - Root of the git repository. -sub git_root -{ - return $globals{git_root} if (defined $globals{git_root}); - - open COMMAND, "git rev-parse --show-toplevel |"; - my $root = <COMMAND>; - close COMMAND; - chomp $root; - - die "Unable to determine git_root" if ($root eq ""); - print "Found git_root at $root\n" if $debug; - - $globals{git_root} = $root; - return $root; -} - -# sub git_commit_history -# -# Determines all the commits between two points in git history. -# -# @param[in] start - Beginning commit. -# @param[in, optional] not_including - Starting point to exclude. -# -# @return array - Commit history. -# -sub git_commit_history -{ - my $start = shift; - my $not_including = shift; - - my @commits = (); - - unless ($not_including eq "") { $not_including = "^".$not_including; } - - open COMMAND, "git rev-list --cherry-pick $start $not_including |"; - while (my $line = <COMMAND>) - { - chomp $line; - push @commits, $line; - } - close COMMAND; - - return \@commits; -} - -# sub git_log_changeId -# -# Determines if a changeId exists in the base -# -# @param[in] base -# @param[in] changeId -# -# @return bool - True if in commit history, False otherwise. -# -sub git_log_changeId -{ - my $base = shift; - my $changeId = shift; - my $exists = 0; - open COMMAND, "git log $base | grep \'Change-Id: $changeId\' |"; - if(<COMMAND> ne "") - { - $exists = 1; - } - close COMMAND; - - return $exists; -} - -# sub git_name_rev -# -# Transforms a git commit number to a symbolic name for human readability. -# -# @param[in] rev - Git revision (commit number) to name. -# @return string - The symbolic name git uses for that commit number. -# -sub git_name_rev -{ - my $rev = shift; - - open COMMAND, "git name-rev $rev |"; - my $line = <COMMAND>; chomp $line; - close COMMAND; - - return $line; -} - -# sub git_commit_deps -# -# Determines a list of dependent commits based on common files touched. -# -# @param[in] base - The end point, in git history, of commits to compare. -# @param[in] commit - The commit to find dependents of. -# -# @return array - List of dependent commits. -# -sub git_commit_deps -{ - my $base = shift; - my $commit = shift; - chomp($base); - chomp($commit); - - my @deps = (); - - print "Searching for deps for $commit against $base\n" if $debug; - - my @files = split('\n',`git diff-tree --name-only --no-commit-id -r $commit`); - foreach my $file (@files) - { - # If a commit introduces a new file, don't run rev-list as it fails - # when the file does not exists in base. - my $file_in_base = `git log $base -n1 --oneline -- $file`; - next if ($file_in_base eq ""); - - my $dep_commit = `git rev-list $commit~1 ^$base $file`; - if ($dep_commit ne "") - { - print "Found dep: $dep_commit" if $debug; - - chomp $dep_commit; - push @deps, $dep_commit; - } - } - - return \@deps; -} - -# sub git_commit_files -# -# Find the files touched by a commit. -# -# @param[in] commit - The commit to examine. -# @return array - List of files touched by the commit. -# -sub git_commit_files -{ - my $commit = shift; - - my @files = (); - open COMMAND, "git diff-tree --name-only --no-commit-id -r $commit |"; - while (my $line = <COMMAND>) - { - chomp $line; - push @files, $line; - } - close COMMAND; - - return \@files; -} - -# sub git_get_subject -# -# Get the subject of the commit message associated with a commit. -# See git log --oneline. -# -# @param[in] commit - The commit to examine. -# @return string - The subject of the commit. -# -sub git_get_subject -{ - my $commit = shift; - - open COMMAND, "git log -n1 --pretty=\"%s\" $commit |"; - my $subject = <COMMAND>; chomp($subject); - close COMMAND; - - return $subject; -} - -# sub git_commit_msg -# -# Get the entire commit message associated with a commit. -# -# @param[in] commit - The commit to examine. -# @return string - The commit message. -# -sub git_commit_msg -{ - my $commit = shift; - - open COMMAND, "git log -n1 --pretty=%B $commit |"; - my $message = ""; - while (my $line = <COMMAND>) - { - $message = $message.$line; - } - close COMMAND; - - return $message; -} - -# sub git_create_branch -# -# Create a branch for a release-level. -# -# @param[in] level - The release-level to use as basis for the branch name. -# @param[in] base - The commit to use as the base for the new branch. -# -sub git_create_branch -{ - my $level = shift; - my $base = shift; - - system("git checkout -b __hbRelease_$level $base"); - die "Could not create branch for $level" if ($?); -} - -# sub git_create_tag -# -# Create a tag for a release-level. -# -# @param[in] level - The release-level to create a tag for. -# @param[in] level_info - The level-info associated with the level. -# -sub git_create_tag -{ - my $level = shift; - my $level_info = shift; - - # Create an annotated tag, taking annotation from stdin. - open COMMAND, "| git tag -a $level -F -" || die; - - # Add information about the level to the tag. - print COMMAND "Release: $level\n\n"; - print COMMAND "Base: ".$level_info->{base}."\n"; - print COMMAND "Previous-Release: ".$level_info->{released}."\n"; - print COMMAND "Branch: ".$globals{"branch"}."\n"; - print COMMAND "\n"; - foreach my $patch (@{$level_info->{patches}}) - { - print COMMAND "Patch: $patch\n"; - } - my $forceDeps = $level_info->{forceDeps}; - foreach my $from (keys %{$forceDeps}) - { - print COMMAND "Forced-Dep: $from:".$forceDeps->{$from}."\n"; - } - - # Commit annotated tag. - close COMMAND; -} - -# sub git_cherry_pick -# -# Cherry-pick a commit onto the current branch. -# -# @param[in] commit - The commit to cherry-pick. -# -# @retval false - Error occurred during cherry-pick. -sub git_cherry_pick -{ - my $commit = shift; - - system("git cherry-pick -x $commit"); - return ($? == 0); -} - -# sub git_order_commits -# -# Order a list of commits so that they are in a good order with regard to -# dependencies. The order returned should be the most likely to not fail -# a cherry-pick sequence. -# -# @param[in] patches - The list of commits to order. -# @param[in] level_info - The level_info for the release-level being created. -# -# @return array - Re-ordered list of commits (from patches). -# -sub git_order_commits -{ - my $patches = shift; - my $level_info = shift; - my $forceDeps = $level_info->{forceDeps}; - my %patch_dep = (); - - # Create patch -> { distance -> 0, deps -> [] } hash. - my %patch_hash = - map { $_ => \{ distance => 0, deps => [] }} @{$patches}; - - # Determine dependencies and distance for each patch. - foreach my $patch (@{$patches}) - { - # Add dependencies for each patch to the hash. - my $deps = git_commit_deps($level_info->{base}, $patch); - push @{${$patch_hash{$patch}}->{deps}}, @{$deps}; - - # Add dependencies to hash for circular depends check later - foreach my $dep (@{$deps}) - { - $patch_dep{$patch}{$dep} = 1; - } - - # Determine the distance from previous release for each patch. - ${$patch_hash{$patch}}->{distance} = - scalar @{git_commit_history($patch, $level_info->{released})}; - } - - # Determine forced dependencies for each patch. - foreach my $patch (keys %{$forceDeps}) - { - my $resolve_from = @{gerrit_resolve_patches([$patch])}[0]; - my $resolve_to = - @{gerrit_resolve_patches([$forceDeps->{$patch}])}[0]; - - print "Force dep: $resolve_from : $resolve_to\n" if ($debug); - - push @{${$patch_hash{$resolve_from}}->{deps}}, $resolve_to; - # Add dependencies to hash for circular depends check later - $patch_dep{$resolve_from}{$resolve_to} = 1; - } - - # Calculate Dijkstra's on the patches. - my $changed = 1; - while ($changed != 0) - { - $changed = 0; - foreach my $patch (@{$patches}) - { - my $distance = 1 + max( map - { - # If patches have a circular dependency, ignore distance check. - next if ($patch_dep{$_}{$patch} && $patch_dep{$patch}{$_}); - ${$patch_hash{$_}}->{distance} - } - @{${$patch_hash{$patch}}->{deps}}); - if ($distance > ${$patch_hash{$patch}}->{distance}) - { - $changed = 1; - ${$patch_hash{$patch}}->{distance} = $distance; - } - } - } - - # Sort the patches based on shortest distance from previous release - # (after Dijkstra). - my @commit_order = - sort { ${$patch_hash{$a}}->{distance} <=> - ${$patch_hash{$b}}->{distance} } - @{$patches}; - - return \@commit_order; -} - -# sub config_filename -# -# @return The location of the hbRelease config file. -# -sub config_filename -{ - return git_root()."/.git/hbRelease.config"; -} - -# sub config_init -# -# Ensures the hbRelease tool is initialized properly. -# -sub config_init -{ - return if (defined $globals{config_init}); - - unless (-e config_filename()) - { - open COMMAND, "git config --get remote.gerrit.url |"; - my $url = <COMMAND>; - close COMMAND; - chomp $url; - - die "Undefined git-remote 'gerrit'" if ($url eq ""); - - die "Unexpected url found: $url" if (not ($url =~ m/ssh:\/\/.*\/.*/)); - - my $server = $url; - my $project = $url; - - $server =~ s/ssh:\/\/(.*)\/.*/$1/; - $project =~ s/.*\/(.*)/$1/; - - print "Gerrit Server: ".$server."\n" if $debug; - print "Gerrit Project: ".$project."\n" if $debug; - - open(UNUSED, ">".config_filename()) || die; - close UNUSED; - - system("git config --file ".config_filename(). - " --add releaseLevels.server $server"); - system("git config --file ".config_filename(). - " --add releaseLevels.project $project"); - } - $globals{config_init} = 1; - -} - -# sub config_list_levels -# -# Determines the previously defined release-levels. -# -# @return hash - { level => 1 } for each defined level. -# -sub config_list_levels -{ - return $globals{config_list_levels} - if (defined $globals{config_list_levels}); - - config_init(); - - open COMMAND, "git config --file ".config_filename(). - " --get-all releaseLevels.levelname |"; - my $names = {}; - while (my $line = <COMMAND>) - { - chomp $line; - $names->{$line} = 1; - } - close COMMAND; - - $globals{config_list_levels} = $names; - return $names; -} - -# sub config_add_level -# -# Add a new level definition to the config file. -# -# @param level_def - A level info with the name/base/released for the new level. -# -sub config_add_level -{ - config_init(); - - my $level_def = shift; - my $levels = config_list_levels(); - - if (defined $levels->{$level_def->{name}}) - { - die "Level ".$level_def->{name}." is already defined"; - } - - system("git config --file ".config_filename(). - " --add releaseLevels.levelname ".$level_def->{name}); - - system("git config --file ".config_filename(). - " --add level.".$level_def->{name}.".base ".$level_def->{base}); - - system("git config --file ".config_filename(). - " --add level.".$level_def->{name}.".released ". - $level_def->{released}); - - if ($globals{"branch"} ne "master") - { - system("git config --file ".config_filename(). - " --add level.".$level_def->{name}.".branch ". - $globals{"branch"}); - } -} - -# sub config_del_level -# -# Delete a level definition from the config file. -# -# @param level - The level name to delete. -# -sub config_del_level -{ - config_init(); - - my $level = shift; - - system("git config --file ".config_filename(). - " --unset releaseLevels.levelname ^".$level."\$"); - - system("git config --file ".config_filename(). - " --remove-section level.".$level); -} - -# sub config_add_patch -# -# Add a patch to a level definition. -# -# @param level - The level to add patch to. -# @param patch - The patch to add. -# -sub config_add_patch -{ - my $level = shift; - my $patch = shift; - - config_get_level($level); - - unless (gerrit_is_patch($patch)) - { - $patch = git_resolve_ref($patch); - } - die "Unknown patch requested" if ($patch eq ""); - - system("git config --file ".config_filename(). - " --add level.$level.patch $patch"); -} - -# sub config_add_dep -# -# Add a forced dependency to a level definition. -# -# @param level - The level to add to. -# @param from - The decendent patch. -# @param to - THe ancestor patch. -# -sub config_add_dep -{ - my $level = shift; - my $from = shift; - my $to = shift; - - config_get_level($level); - - unless (gerrit_is_patch($from)) - { - $from = git_resolve_ref($from); - } - die "Unknown patch requested for 'from' dep" if ($from eq ""); - - unless (gerrit_is_patch($to)) - { - $to = git_resolve_ref($to); - } - die "Unknown patch requested for 'to' dep" if ($to eq ""); - - system("git config --file ".config_filename(). - " --add level.$level.forceDep $from:$to"); -} - -# sub config_get_level -# -# Reads a level's information from the config file. -# -# @param level - The level to read. -# -# @return hash - { name => level, base => base release, -# released => previous release, -# patches => array of patches, -# forceDep => hash of { from => to } pairs }. -# -sub config_get_level -{ - config_init(); - - my $level = shift; - my %level_data = (); - - open COMMAND, "git config --file ".config_filename(). - " --get releaseLevels.levelname $level |"; - my $found_level = <COMMAND>; chomp($found_level); - close COMMAND; - - die "Level $level not defined" if ($found_level eq ""); - - $level_data{name} = $level; - - open COMMAND, "git config --file ".config_filename(). - " --get level.$level.base |"; - my $base = <COMMAND>; chomp($base); - close COMMAND; - - $level_data{base} = $base; - - open COMMAND, "git config --file ".config_filename(). - " --get level.$level.released |"; - my $released = <COMMAND>; chomp($released); - close COMMAND; - - $level_data{released} = $released; - - open COMMAND, "git config --file ".config_filename(). - " --get level.$level.branch |"; - my $branch = <COMMAND>; chomp($branch); - close COMMAND; - - if ($branch ne "") - { - $globals{"branch"} = $branch; - } - - my @patches = (); - open COMMAND, "git config --file ".config_filename(). - " --get-all level.$level.patch |"; - while (my $patch = <COMMAND>) - { - chomp($patch); - push @patches, $patch; - } - close COMMAND; - - $level_data{patches} = \@patches; - - my %forceDeps = (); - open COMMAND, "git config --file ".config_filename(). - " --get-all level.$level.forceDep |"; - while (my $forceDep = <COMMAND>) - { - $forceDep =~ m/(.*):(.*)/; - $forceDeps{$1} = $2; - } - close COMMAND; - - $level_data{forceDeps} = \%forceDeps; - - return \%level_data; -} - -# sub config_print_levels -# -# Displays the name of each defined level. -# -sub config_print_levels -{ - my $levels = config_list_levels(); - foreach my $level (sort keys %$levels) - { - print $level."\n"; - } -} - -# sub config_server -# -# Gets the Gerrit server name / address from the config file. -# -# @return string - The location of the Gerrit server. -# -sub config_server -{ - return $globals{config_server} if (defined $globals{config_server}); - - config_init(); - - open COMMAND, "git config --file ".config_filename(). - " --get releaseLevels.server |"; - my $server = <COMMAND>; chomp($server); - close COMMAND; - - die "Server config does not exist" if ($server eq ""); - - $globals{config_server} = $server; - return $server; - -} - -# sub config_project -# -# Gets the Gerrit project managed by this repository from the config file. -# -# @return string - Project managed by this repository. -# -sub config_project -{ - return $globals{config_project} if (defined $globals{config_project}); - - config_init(); - - open COMMAND, "git config --file ".config_filename(). - " --get releaseLevels.project |"; - my $project = <COMMAND>; chomp($project); - close COMMAND; - - die "Project config does not exist" if ($project eq ""); - - $globals{config_project} = $project; - return $project; -} - -# sub config_resolve_level_dep -# -# Resolves dependencies for patches by parsing the commit messages for the -# depends-on tag and checking if there are any open parents of a commit. -# If a patch is dependent on a patch not already in the level, the patch is -# added. -# -# @param[in] - level name -# @param[in] - Array of patches to process. -# -# @TODO RTC:125235 - improve this to support cross project dependencies -sub config_resolve_level_dep -{ - print "Resolving level dependencies...\n"; - my $level = shift; - my $base = shift; - my @patches = @_; - my %level_patches = (); - - while (@patches) - { - my $patchPair = shift @patches; - my ($patch,$patchSet) = split (":", $patchPair); - - # Check if patch has already been added to level - if ($level_patches{$patch}) - { - print "Skipping - already added patch = $patch to level\n" if $debug; - next; - } - # Check if patch already exists in release base - if (git_log_changeId($base, $patch)) - { - print "Skipping - patch = $patch already exists in release base = $base\n" if $debug; - next; - } - - # Mark patch as processed - $level_patches{$patch} = 1; - - print "\n===========\nFirst time seeing patch = $patch\n" if $debug; - - # Force use of changeId's - if (!gerrit_is_patch($patch)) - { - die "Added patch: $patch is not of type changeId\n"; - } - - # Add patch to level with resolved git commit. - print "Adding patch - $patchPair\n" if $debug; - my $commits = gerrit_resolve_patchset([$patchPair]); - config_add_patch($level, $commits->[0]); - - # Get commit message - my $patchInfo = gerrit_query_commit($patch); - my @commitMsgArray = split(/\\n/,$patchInfo->{commitMessage}); - print Dumper @commitMsgArray if $debug; - - # Check for OPEN parent - my $commit_info = gerrit_query_commit($patch); - my $parent_commit = $commit_info->{currentPatchSet}->{parents}[0]; - # Check if parent already merged into base branch - if (!commit_local($base, $parent_commit)) - { - my $parent_info = gerrit_query_commit($parent_commit); - if ($parent_info->{status} eq "NEW") - { - my $parent_id = $parent_info->{id}; - # Add dependency if dependency is not already in base release - if(!git_log_changeId($base, $parent_id)) - { - print "Adding forced dependency $patch:$parent_id\n" if $debug; - config_add_dep($level, $patch, $parent_id); - } - - # Add dependent patch if not already added to level - if (!exists($level_patches{$parent_id}) ) - { - push @patches, $parent_id; - } - } - } - - # Search commit message for dependencies - foreach my $line (@commitMsgArray) - { - # Check for forced dependencies - if ($line =~ m/depends-on:/i) - { - $line =~ s/([^:]*):\s*//; - chomp($line); - print "Found depends-on: $line\n" if $debug; - - # Add dependency if dependency is not already in base release - if(!git_log_changeId($base, $line)) - { - print "Adding forced dependency $patch:$line\n" if $debug; - config_add_dep($level, $patch, $line); - } - - # Add dependent patch if not already added to level - if (!exists($level_patches{$line}) ) - { - push @patches, $line; - } - } - # Print out CMVC dependencies - if ($line =~ m/cmvc-([a-zA-Z]+):/i) - { - print "$TOKEN Need ".$line."\n"; - } - } - } -} - -# sub config_verify_patches -# -# Verify patch-list to ensure all dependencies are met -# -# @param[in] - level base patch -# @param[in] - Array of patches to verify. -# -sub config_verify_patches -{ - print "Verifying patches...\n"; - - config_init(); - - my $base = shift; - my $patches = shift; - - foreach my $patch (@{$patches}) - { - print "Deps for $patch\n" if $debug; - my $displayed_header = 0; - - my $deps = git_commit_deps($base, $patch); - - foreach my $dep (@{$deps}) - { - unless (grep {$_ eq $dep} @{$patches}) - { - unless ($displayed_header) - { - print "-------------------------------------------------\n"; - print "Potential missing dependency for:\n"; - print wrap(" "," ",git_get_subject($patch)."\n"); - print "\t$patch\n\n"; - $displayed_header = 1; - } - - print wrap(" ", " ", git_get_subject($dep)."\n"); - print "\t$dep\n"; - - my $files = array_intersect(git_commit_files($patch), - git_commit_files($dep)); - - foreach my $file (@{$files}) - { - print "\t$file\n"; - } - - print "\n"; - } - } - - if ($displayed_header) - { - print "-------------------------------------------------\n"; - } - } - -} - -# sub config_release -# -# Create a branch / tag based on the definition of a release. -# -# @param[in] - level info -# @param[in] - bool to create tag -# -sub config_release -{ - my $level_info = shift; - my $create_tag = shift; - - print "Creating release branch...\n"; - git_create_branch($level_info->{name}, $level_info->{base}); - - my $patches = $level_info->{patches}; - - print "Resolving and ordering patches...\n"; - print Dumper $level_info->{patches} if $debug; - $patches = gerrit_resolve_patches($level_info->{patches}); - $patches = git_order_commits($patches, $level_info); - - print "\n========\nDetermined patch order as:\n"; - my $i = 1; - foreach my $patch (@{$patches}) - { - print "$i. $patch\n"; - $i++; - } - - print "\n========\nApplying patches...\n"; - $i = 1; - foreach my $patch (@{$patches}) - { - print "\n$i. Cherry-picking commit = $patch.\n\n"; - unless (git_cherry_pick($patch)) - { - print `git status`; - system("git reset HEAD --hard"); - die "Cherry-pick of $patch failed"; - } - $i++; - } - - print "\nGenerating release notes...\n"; - create_release_notes($level_info->{name}, $level_info); - - if ($create_tag) - { - print "\nCreating tag...\n"; - git_create_tag($level_info->{name}, $level_info); - } -} - -sub publish_cq -{ - my ($level, $track, $released) = @_; - - my $commits = git_commit_history($level, $released); - - bq_add_releaseList($level, $track, $commits); - - foreach my $commit (@{$commits}) - { - my $changeid = gerrit_changeid_num($commit); - my $cq = cq_workitem_num($commit); - my $commitMessage = git_commit_msg($commit); - if ($cq ne "") - { - print "Change-Id: $changeid\n" if ($debug); - print "CQ: $cq\n" if ($debug); - - bq_add_releasenote($cq, $changeid, $level, $track, $commitMessage); - } - } -} - -# -# Sub print_debug_info -# @brief This subroutine prints out some important information at the -# end of Phase 2 of the Automatic Release process. -# - -sub print_debug_info -{ - my ($level, $feature, $cq_id, $released) = @_; - - - print "\n\nHostboot Release debugging information.....\n"; - print "\nHostboot Official Release Notes\n"; - - print "Level $level Included commits:\n"; - - my $commits = git_commit_history($level,$released); - foreach my $commit (@{$commits}) - { - my $cq = cq_workitem_num($commit); - my $rtc = rtc_workitem_num($commit); - my $changenum = ""; - my $subject = git_get_subject($commit); - - # Find if the commit has a CQ # or an RTC #. - if ($cq ne "") - { - $changenum = "$cq "; - } - elsif ($rtc ne "") - { - $changenum = "$rtc "; - } - else - { - $changenum = "--------- "; - } - - print "$changenum$subject\n"; - } - - print "\nThe Bestquest track number is $cq_id\n"; - print "And the Bestquest link is http://w3.rchland.ibm.com/projects/bestquest/?defect=$cq_id&table=requirement\n\n"; - print "The release feature number is $feature\n"; - print "This release this is based on is $released\n"; - -} - -# sub gerrit_ssh_command -# -# Creates a properly formed ssh command based on the server address. -# -# @return string - The basic ssh command to connect to the server. -# -sub gerrit_ssh_command -{ - return $globals{gerrit_ssh_command} - if (defined $globals{gerrit_ssh_command}); - - my $server = config_server(); - my $port = ""; - - if ($server =~ m/.*:.*/) - { - $port = $server; - $server =~ s/(.*):.*/$1/; - $port =~ s/.*:(.*)/$1/; - - $port = "-p $port"; - } - - my $command = "ssh -qx $port $server gerrit"; - print "SSH command: $command\n" if $debug; - - $globals{gerrit_ssh_command} = $command; - return $command; -} - -# sub gerrit_query -# -# Performs a gerrit query and parses the resulting JSON. -# -# @param[in] query - The query to perform. -# -# @return array - A list of items from the JSON query. Each item is a -# hash (key-value pair) for the item attributes. -# -sub gerrit_query -{ - my $query = shift; - - my @items = (); - - open COMMAND, gerrit_ssh_command()." query $query --current-patch-set". - " --patch-sets --format=JSON |"; - - while (my $line = <COMMAND>) - { - chomp $line; - push @items, json_parse($line); - } - - return \@items; -} - -# sub gerrit_query_commit -# -# Performs a gerrit query on a specific commit. -# -# @param[in] commit - The commit to query. -# -# @return hash - The parsed JSON for the queried commit. -# -sub gerrit_query_commit -{ - my $commit = shift; - - my $project = config_project(); - - - my $query_result = gerrit_query("$commit project:$project ". - "branch:".$globals{"branch"}); - foreach my $result (@{$query_result}) - { - if ($result->{id} eq $commit || - $result->{currentPatchSet}->{revision} =~ m/$commit/) - { - return $result; - } - else - { - # If all patchsets queried, search all of them for the commit - foreach my $patchset (@{$result->{patchSets}}) - { - if ($patchset->{revision} =~ m/$commit/) - { - return $result; - } - } - } - } -} - -# sub gerrit_is_patch -# -# Determines if a patch identifier is a Gerrit patch or not. -# -# @param[in] i_patch - The patch to make determination about. -# -# @retval true - Patch is a Gerrit patch ID. -# @retval false - Patch does not appear to be a Gerrit patch ID. -sub gerrit_is_patch -{ - my $i_patch = shift; - chomp($i_patch); - return 1 if ($i_patch =~ m/I[0-9a-f]+/); - return 0; -} - -# sub gerrit_resolve_patches -# -# Resolves gerrit patch IDs to git commit numbers and ensures the git -# commits are fetched from the gerrit server. -# -# Any git commit number is left unchanged. -# -# @param[in] patches - An array of patches. -# @return array - An array of git commit numbers. -# -sub gerrit_resolve_patches -{ - my $patches = shift; - my @result = (); - - foreach my $patch (@{$patches}) - { - if (gerrit_is_patch($patch)) - { - my $patch_info = gerrit_query_commit($patch); - gerrit_fetch($patch_info->{currentPatchSet}->{ref}); - push @result, $patch_info->{currentPatchSet}->{revision}; - } - else - { - push @result, $patch; - } - } - - return \@result; -} - -# sub gerrit_resolve_patchset -# -# Resolves an array of gerrit change-id and patch-set pairs to git commit -# numbers and and ensures the git commits are fetched from the gerrit server. -# -# @param[in] patches - An array of change-id, patch-set pairs. -# @return array - An array of git commit numbers. -# -sub gerrit_resolve_patchset -{ - my $patches = shift; - - my @result = (); - foreach my $patchPair (@{$patches}) - { - my ($changeId,$patchSet) = split(":",$patchPair); - - if (gerrit_is_patch($changeId)) - { - my $patch_info = gerrit_query_commit($changeId); - # Fail if patchset DNE - if ($patchSet > $patch_info->{currentPatchSet}->{number}) - { - die "$patchSet does not have patch number $patchSet"; - } - # JSON creates array of patchSets in number order - my $index = $patchSet - 1; - gerrit_fetch($patch_info->{patchSets}[$index]->{ref}); - push @result, $patch_info->{patchSets}[$index]->{revision}; - } - else - { - die "Requires gerrit change-id and patch-set"; - } - } - - return \@result; -} - -# sub gerrit_fetch -# -# Fetches the contents of a Gerrit revision (refs/changes/*) to the local -# git repository. -# -# @param[in] ref - The revision to fetch from the Gerrit server. -# -sub gerrit_fetch -{ - my $ref = shift; - - system("git fetch gerrit $ref -q"); -} - -# sub rtc_workitem_num -# -# Determines the RTC WorkItem associated with a git commit. -# -# @param[in] commit - The git commit. -# -# @return string - RTC WorkItem number (or ""). -# -sub rtc_workitem_num -{ - my $commit = shift; - my $message = git_commit_msg($commit); - - if ($message =~ m/RTC:\s*([0-9]+)/) - { - return $1; - } - else - { - return ""; - } -} - -# sub cq_workitem_num -# -# Determine the CQ WorkItem associated with a git commit. -# -# @param[in] commit - The git commit. -# -# @return string - CQ WorkItem number (or ""). -# -sub cq_workitem_num -{ - my $commit = shift; - my $message = git_commit_msg($commit); - - if ($message =~ m/CQ:\s*([A-Z][A-Z][0-9]+)/) - { - return $1; - } - else - { - return ""; - } -} - -# sub coreq_workitem_num -# -# Search through a git commit for all coReq instances. -# -# @param[in] commit - The git commit. -# -# @return array of strings - CMVC-Coreq numbers or "". -# - -sub coreq_workitem_num -{ - my $commit = shift; - - my @msg_lines = split('\n',git_commit_msg($commit)); - my @coreqs = (); - - foreach my $line (@msg_lines) - { - if ($line =~ m/CMVC-Coreq:\s*([0-9]+)/i) - { - push @coreqs, $1; - } - } - return @coreqs; -} - -# sub prereq_workitem_num -# -# Search through a git commit for all preReq instances. -# -# @param[in] commit - The git commit. -# -# @return array of strings - CMVC-Prereq numbers or "". -# - -sub prereq_workitem_num -{ - my $commit = shift; - - my @msg_lines = split('\n',git_commit_msg($commit)); - my @prereqs = (); - - foreach my $line (@msg_lines) - { - if($line =~ m/CMVC-Prereq:\s*([0-9]+)/i) - { - push @prereqs, $1; - } - } - return @prereqs; -} - -# sub gerrit_changeid_num -# -# Determine the Gerrit Change-Id associated with a git commit. -# -# @param[in] commit - The git commit. -# -# @return string - Gerrit Change-Id number (or ""). -# -sub gerrit_changeid_num -{ - my $commit = shift; - my $message = git_commit_msg($commit); - - if ($message =~ m/Change-Id:\s*(I[0-9a-z]+)/) - { - return $1; - } - else - { - return ""; - } -} - - -# sub rtc_hyperlink -# -# Turn an RTC WorkItem number into the https:// address to the RTC server. -# -# @param[in] workitem - RTC workitem number. -# -# @return string - The https:// address of the RTC item on the server. -# -sub rtc_hyperlink -{ - my $workitem = shift; - return "https://jazz07.rchland.ibm.com:13443/jazz/oslc/workitems/". - "$workitem.hover.html"; -} - -# sub cq_hyperlink -# -# Turn a CQ WorkItem number into the http:// address to the BQ server. -# -# @param[in] workitem - CQ workitem number. -# -# @return string - The http:// address of the CQ item on the server. -# -sub cq_hyperlink -{ - my $workitem = shift; - return "http://w3.rchland.ibm.com/projects/bestquest/?defect=$workitem"; -} - -# sub json_parse -# -# Parse a line of JSON into an hash-object. -# -# @param[in] line - The JSON content. -# -# @return hash - The parsed object. -# -# @note There are perl modules for doing this but they are not installed on -# the pool machines. The parsing for JSON (at least the content from -# the Gerrit server) isn't so bad... -# -sub json_parse -{ - my $line = shift; - - die "Invalid JSON format: $line" unless ($line =~ m/^\{.*\}$/); - $line =~ s/^\{(.*)}$/$1/; - - my %object = (); - - while($line ne "") - { - my $key; - my $value; - - ($key, $line) = json_get_string($line); - $key =~ s/^"(.*)"$/$1/; - - $line =~ s/^://; - if ($line =~ m/^"/) - { - ($value, $line) = json_get_string($line); - $value =~ s/^"(.*)"$/$1/; - } - elsif ($line =~ m/^{/) - { - ($value, $line) = json_get_object($line); - $value = json_parse($value); - } - elsif ($line =~ m/^\[/) - { - ($value, $line) = json_get_array($line); - $value = json_parse_array($value); - } - else - { - $line =~ s/([^,]*)//; - $value = $1; - } - - $object{$key} = $value; - } - - return \%object; -} - -# sub json_parse_array -# -# Utility function for json_parse. -# -sub json_parse_array -{ - my $line = shift; - - $line =~ s/^\[(.*)\]$/$1/; - - my @array = (); - - while ($line ne "") - { - my $value; - - if ($line =~ m/^"/) - { - ($value, $line) = json_get_string($line); - $value =~ s/^"(.*)"$/$1/; - } - elsif ($line =~ m/^\{/) - { - ($value, $line) = json_get_object($line); - $value = json_parse($value); - } - elsif ($line =~ m/^\[/) - { - ($value, $line) = json_get_array($line); - $value = json_parse_array($value); - } - else - { - $line =~ s/([^,]*)//; - $value = $1; - } - - push @array, $value; - $line =~ s/^,//; - } - - return \@array; -} - -# sub json_get_string -# -# Utility function for json_parse. -# -sub json_get_string -{ - my $line = shift; - - $line =~ /("[^"]*")(.*)/; - my $first = $1; - my $second = $2; - - if ($first =~ m/\\"$/) - { - my ($more, $rest) = json_get_string($second); - return ($first.$more , $rest); - } - else - { - return ($first, $second); - } -} - -# sub json_get_object -# -# Utility function for json_parse. -# -sub json_get_object -{ - my $line = shift; - - $line =~ s/^{//; - my $object = "{"; - my $frag = ""; - - my $found_object = 0; - - until ((not $found_object) && ($object =~ m/}$/)) - { - $found_object = 0; - - if ($line =~ m/^\{/) - { - ($frag, $line) = json_get_object($line); - $object = $object.$frag; - $found_object = 1; - } - elsif ($line =~ m/^"/) - { - ($frag, $line) = json_get_string($line); - $object = $object.$frag; - } - elsif ($line =~ m/^\[/) - { - ($frag, $line) = json_get_array($line); - $object = $object.$frag; - } - elsif ($line =~ m/^[:,}]/) - { - $line =~ s/^([:,}])//; - $frag = $1; - $object = $object.$frag; - } - else - { - $line =~ s/([^,}]*)//; - $frag = $1; - $object = $object.$frag; - } - } - - return ($object, $line); -} - -# sub json_get_array -# -# Utility function for json_parse. -# -sub json_get_array -{ - my $line = shift; - - $line =~ s/^\[//; - my $array = "["; - my $frag = ""; - - my $found_array = 0; - - until ((not $found_array) && ($array =~ m/]$/)) - { - $found_array = 0; - - if ($line =~ m/^\[/) - { - ($frag, $line) = json_get_array($line); - $array = $array.$frag; - $found_array; - } - elsif ($line =~ m/^\{/) - { - ($frag, $line) = json_get_object($line); - $array = $array.$frag; - } - elsif ($line =~ m/^"/) - { - ($frag, $line) = json_get_string($line); - $array = $array.$frag; - } - elsif ($line =~ m/^[:,\]]/) - { - $line =~ s/^([:,\]])//; - $frag = $1; - $array = $array.$frag; - } - else - { - $line =~ s/([^,]*)//; - $frag = $1; - $array = $array.$frag; - } - } - - return ($array, $line); -} - -# sub array_intersect -# -# Perform set intersection on two arrays. -# -# @param[in] one - The first array. -# @param[in] two - The second array. -# -# @return array - The set intersection. -# -sub array_intersect -{ - my $one = shift; - my $two = shift; - - my %set = {}; - - map { $set{$_}++ } (@{$one}, @{$two}); - - my @result = map { ($set{$_} > 1) ? $_ : () } (keys %set); - - return \@result; -} - - # globals used to store the cookie file name for logging into BQ. -my $cookie_fh = ""; -my $cookie_name = ""; - -use constant BQ_SERVER => "http://w3.rchland.ibm.com/projects/bestquest/"; - -# sub bq_login -# -# Login to the BestQuest website. -# -sub bq_login -{ - return if ($cookie_name ne ""); - - my %bq_login_params = ( user => "UNKNOWN", - passwd => "UNKNOWN", - database => "AIXOS", - schema => "STGC_AIX", - cqserver => "auscqweb.austin.ibm.com", - cqport => "6600" ); - - # Read username / password. - $bq_login_params{user} = $globals{email}; - my $password = `cat $HOSTBOOT_GSA_HOME/private/password`; - die $? if $?; - chomp($password); - $bq_login_params{passwd} = $password; - - # Create parameters. - my $login_post = "verb=login_form_response"; - foreach my $key (keys %bq_login_params) - { - $login_post = $login_post."&login_".$key."=".$bq_login_params{$key}; - } - - # Create a tempfile to hold the cookies. - ($cookie_fh, $cookie_name) = tempfile(UNLINK => 1); - - # Do login. - system "wget -q -O - --save-cookies $cookie_name ". - "--post-data '$login_post' ".BQ_SERVER." > /dev/null"; -} - -# sub bq_add_releasenote -# -# Adds a string "Change W added to Hostboot level X and released under Y. -# "Commit Message: Z" -# to a CQ defect / feature. -# -# @param[in] - CQ defect / feature. -# @param[in] - Corresponding Gerrit Change-Id. -# @param[in] - Hostboot release level. -# @param[in] - Hostboot release track. -# @param[in] - Hostboot commit message -# -sub bq_add_releasenote -{ - my $cq = shift; - my $change_id = shift; - my $level = shift; - my $release = shift; - my $commitMessage = shift; - - my $note = "Change%20$change_id%20added%20to%20Hostboot%20level%20". - "$level%20and%20released%20under%20$release%0A". - "Commit%20Message%3A%0A$commitMessage"; - - # Login to BQ. - bq_login(); - - print "Updating release note for $cq.\n"; - - # Find CQ ID for defect/feature. - my $cqid_cmd = "wget -q -O - --load-cookies $cookie_name ". - BQ_SERVER."?defect=$cq | grep 'CQ ID:' -A1 | tail -n1 | ". - "sed 's/<\\/a.*//' | sed 's/.*recordType=//' | ". - "sed 's/\">/ /'"; - - my $cqid_result = `$cqid_cmd`; - chomp $cqid_result; - - my ($cqtype,$cqid) = split / /, $cqid_result; - - # Add release comment. - system "wget -q -O - --load-cookies $cookie_name '".BQ_SERVER. - "?verb=editnote_form_response&table=$cqtype&id=$cqid&uid=$cq&". - "note_string=$note' > /dev/null"; - -} - -# sub bq_add_releaseList -# -# This function is adding the releaseNotes to the release's BestQuest -# The build team wanted to know exactly what was included in each release -# and this is just an easy way to quickly view it. -# -# @param[in] - Hostboot release level. -# @param[in] - Hostboot release track. -# @param[in] - Array of commits in the hostboot level - -sub bq_add_releaseList -{ - my $level = shift; - my $track = shift; - my $commits = shift; - - # Note: when adding notes to BestQuest, everything has to be in ASCII - # for it to display correctly - # %20:' ', %0A:newline, %3D:'=', %3A:':', %2D:'-' - my $note = "Hostboot%20Official%20Release%20Notes%0A"; - - # Adding a seperator ('='x100) between the title and the actual data. - # This posting method doesn't allow for bolding and it needs an eyecatch - for (my $i=0; $i <100; $i++) - { - $note .= "%3D"; - } - $note .= "%0A%0ALevel%3A%20$level%0AIncluded%20commits%3A%0A%0A"; - - foreach my $commit (@{$commits}) - { - my $cq = cq_workitem_num($commit); - my $rtc = rtc_workitem_num($commit); - my $changenum = ""; - my $subject = git_get_subject($commit); - - # Find if the commit has a ClearQuest # or an RTC #, if not blank -'s - if ($cq ne "") - { - $changenum = "$cq%20%20"; #additionally, spacing for readability - } - elsif ($rtc ne "") - { - $changenum = "$rtc%20%20%20%20"; - } - else - { - $changenum = "%2D%2D%2D%2D%2D%2D%2D%2D%2D%20"; #--------- - } - $note .= "$changenum$subject%20%20%0A"; - - # Adding in hb commit hash below the Commit number and subject - $note .= "%20%20%20%20%20%20%20%20%20%20$commit%0A"; - } - - # Login to BQ. - bq_login(); - - print "Updating release note for hbRelease $level\n"; - - # Find CQ ID for defect/feature. - my $cqid_cmd = "wget -q -O - --load-cookies $cookie_name ". - BQ_SERVER."?defect=$track | grep 'CQ ID:' -A1 | tail -n1 | ". - "sed 's/<\\/a.*//' | sed 's/.*recordType=//' | ". - "sed 's/\">/ /'"; - - my $cqid_result = `$cqid_cmd`; - chomp $cqid_result; - - # Splitting on whitespace to seperate the ClearQuest type and ID - my ($cqtype,$cqid) = split / /, $cqid_result; - - # Add the release notes to the defect for our hbRelease. - # For all commits in this release: CQ/RTC number - Subject of commit - system "wget -q -O - --load-cookies $cookie_name '".BQ_SERVER. - "?verb=editnote_form_response&table=$cqtype&id=$cqid&uid=$track&". - "note_string=$note' > /dev/null"; - -} - -# sub execute_cmvc_reqs -# -# Given a commit, find the CMVC coreqs and prereqs and add these -# tracks to the auto release track. -# -# @param[in] feature - Current Release track in CMVC -# @param[in] level - hostboot level tag -# @param[in] released - previously released hostboot level tag -# @param[in] release - which release this is (e.g. fips910, fips860) -# - -sub execute_cmvc_reqs -{ - my $feature = shift; - my $level = shift; - my $released = shift; - my $release = shift; - - #need to get commit - my $commits = git_commit_history($level, $released); - - foreach my $commit (@{$commits}) - { - my @coreq_list = coreq_workitem_num($commit); - foreach my $coreq (@coreq_list) - { - if($coreq ne "") - { - my $cmd = "/esw/bin/coreqTracks -r $release -t $feature -t2 $coreq -e $globals{email}"; - print "$cmd\n"; - my $output = `echo "y" | $cmd`; - print $output; - } - } - - my @prereq_list = prereq_workitem_num($commit); - foreach my $prereq (@prereq_list) - { - if($prereq ne "") - { - my $cmd = "/esw/bin/prereqTracks -r $release -t $prereq -t2 $feature -e $globals{email}"; - print "$cmd\n"; - my $output = `echo "y" | $cmd`; - print $output - } - } - } -} - -# sub hw_req_check -# -# Check for Hw-Image requirements, and fail so that a manual -# check can be run for the specific commit and added as a CMVC -# requirement. -# -sub hw_req_check -{ - my $level = shift; - my $released = shift; - - my $commits = git_commit_history($level, $released); - - foreach my $commit (@{$commits}) - { - if (($commit =~ m/HW-Image-Coreq:\s*([a-z]+)/i) || - ($commit =~ m/HW-Image-Prereq:\s*([0-9]+)/i)) - { - print "HW Image Req was found:\n$commit\n"; - die "HW-Image-Coreq/Prereq detected.\n"; - } - } -} - -# sub run_system_command -# -# Execute a system command, handle printing command and debug info, and return -# system output for caller processing -# -# E.g. Execute a CMVC line command and return the results. -# -# @param[in] cmd - system command to be executed. -# -# @return string - output returned from running system command. -# -sub run_system_command -{ - my $cmd = shift; - - print "$cmd\n"; - my $output = `$cmd`; - #print "output=$output\n"; - die "failed running system command $cmd - $?" if ($?); - print $output if $debug; - - return $output; -} - -# sub commit_local -# -# Checks if commit is in local tree -# -# @param[in] i_commit - The commit to examine. -# -# @return bool - true if in local tree -# -sub commit_local -{ - my ($i_base, $i_commit) = @_; - chomp($i_base); - chomp($i_commit); - - die "Based is not of type commit (SHA hash)" if (!is_commit($i_base)); - - # Git log will fail if not valid change-id or commit. Note order is check - # for change-id first as it will also match the regex for is_commit - if (gerrit_is_patch($i_commit)) - { - `git log $i_base | grep "Change-Id: $i_commit"`; - ($?) ? return 0 : return 1; - } - elsif(is_commit($i_commit)) - { - # Note '^commit' used to avoid finding the commit in the commit message - # somewhere - `git log $i_base | grep "^commit $i_commit"`; - ($?) ? return 0 : return 1; - } - else - { - die "Commit is not of type commit or change-id"; - } -} - -# sub is_commit -# -# Determines if a patch identifier is a git commit id or not. -# -# @param[in] i_ref - The reference to make determination about. -# -# @return bool - Ref is in the style of a git commit -sub is_commit -{ - my $i_ref = shift; - chomp($i_ref); - - ($i_ref =~ m/[0-9a-f]{7,40}/) ? return 1 : return 0; -} |