#!/usr/bin/perl #################################################################################################################################### # release.pl - PgBackRest Release Manager #################################################################################################################################### #################################################################################################################################### # Perl includes #################################################################################################################################### use strict; use warnings FATAL => qw(all); use Carp qw(confess); use English '-no_match_vars'; $SIG{__DIE__} = sub { Carp::confess @_ }; use Cwd qw(abs_path); use File::Basename qw(dirname); use Getopt::Long qw(GetOptions); use Pod::Usage qw(pod2usage); use Storable; use lib dirname($0) . '/lib'; use lib dirname(dirname($0)) . '/build/lib'; use lib dirname(dirname($0)) . '/lib'; use lib dirname(dirname($0)) . '/test/lib'; use BackRestDoc::Common::Doc; use BackRestDoc::Common::DocConfig; use BackRestDoc::Common::DocManifest; use BackRestDoc::Common::DocRender; use BackRestDoc::Html::DocHtmlSite; use BackRestDoc::Latex::DocLatex; use BackRestDoc::Markdown::DocMarkdown; use pgBackRest::Common::Exception; use pgBackRest::Common::Log; use pgBackRest::Common::String; use pgBackRest::Storage::Local; use pgBackRest::Storage::Posix::Driver; use pgBackRest::Version; use pgBackRestTest::Common::ExecuteTest; #################################################################################################################################### # Usage #################################################################################################################################### =head1 NAME release.pl - pgBackRest Release Manager =head1 SYNOPSIS release.pl [options] General Options: --help Display usage and exit --version Display pgBackRest version --quiet Sets log level to ERROR --log-level Log level for execution (e.g. ERROR, WARN, INFO, DEBUG) Release Options: --build Build the cache before release (should be included in the release commit) --deploy Deploy documentation to website (can be done as docs are updated) --no-coverage Don't generate the coverage report =cut #################################################################################################################################### # Load command line parameters and config (see usage above for details) #################################################################################################################################### my $bHelp = false; my $bVersion = false; my $bQuiet = false; my $strLogLevel = 'info'; my $bBuild = false; my $bDeploy = false; my $bNoCoverage = false; GetOptions ('help' => \$bHelp, 'version' => \$bVersion, 'quiet' => \$bQuiet, 'log-level=s' => \$strLogLevel, 'build' => \$bBuild, 'deploy' => \$bDeploy, 'no-coverage' => \$bNoCoverage) or pod2usage(2); #################################################################################################################################### # Run in eval block to catch errors #################################################################################################################################### eval { # Display version and exit if requested if ($bHelp || $bVersion) { print PROJECT_NAME . ' ' . PROJECT_VERSION . " Release Manager\n"; if ($bHelp) { print "\n"; pod2usage(); } exit 0; } # If neither build nor deploy is requested then error if (!$bBuild && !$bDeploy) { confess &log(ERROR, 'neither --build nor --deploy requested, nothing to do'); } # Set console log level if ($bQuiet) { $strLogLevel = 'error'; } logLevelSet(undef, uc($strLogLevel), OFF); # Set the paths my $strDocPath = dirname(abs_path($0)); my $strDocHtml = "${strDocPath}/output/html"; my $strDocExe = "${strDocPath}/doc.pl"; my $strTestExe = dirname($strDocPath) . "/test/test.pl"; my $oStorageDoc = new pgBackRest::Storage::Local( $strDocPath, new pgBackRest::Storage::Posix::Driver({bFileSync => false, bPathSync => false})); # Determine if this is a dev release my $bDev = PROJECT_VERSION =~ /dev$/; my $strVersion = $bDev ? 'dev' : PROJECT_VERSION; if ($bBuild) { # Remove permanent cache file $oStorageDoc->remove("${strDocPath}/resource/exe.cache", {bIgnoreMissing => true}); # Remove all docker containers to get consistent IP address assignments executeTest('docker rm -f $(docker ps -a -q)', {bSuppressError => true}); # Generate coverage summmary if (!$bNoCoverage) { &log(INFO, "Generate Coverage Summary"); executeTest( "${strTestExe} --no-lint --no-package --no-valgrind --no-optimize --vm-max=3 --coverage-summary", {bShowOutputAsync => true}); } # Generate deployment docs for RHEL/Centos 7 &log(INFO, "Generate RHEL/CentOS 7 documentation"); executeTest("${strDocExe} --deploy --key-var=os-type=centos7 --out=pdf", {bShowOutputAsync => true}); executeTest("${strDocExe} --deploy --cache-only --key-var=os-type=centos7 --out=pdf"); # Generate deployment docs for RHEL/Centos 6 &log(INFO, "Generate RHEL/CentOS 6 documentation"); executeTest("${strDocExe} --deploy --key-var=os-type=centos6 --out=pdf", {bShowOutputAsync => true}); executeTest("${strDocExe} --deploy --cache-only --key-var=os-type=centos6 --out=pdf"); # Generate deployment docs for Debian &log(INFO, "Generate Debian/Ubuntu documentation"); executeTest("${strDocExe} --deploy", {bShowOutputAsync => true}); executeTest("${strDocExe} --deploy --cache-only --out=man --out=html --var=project-url-root=index.html"); } if ($bDeploy) { my $strDeployPath = "${strDocPath}/site"; # Generate docs for the website history &log(INFO, 'Generate website ' . ($bDev ? 'dev' : 'history') . ' documentation'); executeTest( $strDocExe . ($bDev ? '' : ' --deploy --cache-only') . ' --out=html --var=project-url-root=index.html' . ($bDev ? ' --dev --no-exe' : ' --exclude=release')); # Deploy to repository &log(INFO, '...Deploy to repository'); executeTest("rm -rf ${strDeployPath}/prior/${strVersion}"); executeTest("mkdir ${strDeployPath}/prior/${strVersion}"); executeTest("cp ${strDocHtml}/* ${strDeployPath}/prior/${strVersion}"); # Generate docs for the main website if (!$bDev) { &log(INFO, "Generate website documentation"); executeTest("${strDocExe} --deploy --cache-only --out=html"); # Deploy to repository &log(INFO, '...Deploy to repository'); executeTest("rm -rf ${strDeployPath}/dev"); executeTest("find ${strDeployPath} -maxdepth 1 -type f -exec rm {} +"); executeTest("cp ${strDocHtml}/* ${strDeployPath}"); executeTest("cp ${strDocPath}/../README.md ${strDeployPath}"); executeTest("cp ${strDocPath}/../LICENSE ${strDeployPath}"); } # Update permissions executeTest("find ${strDeployPath} -type d -exec chmod 750 {} +"); executeTest("find ${strDeployPath} -type f -exec chmod 640 {} +"); } # Exit with success exit 0; } #################################################################################################################################### # Check for errors #################################################################################################################################### or do { # If a backrest exception then return the code exit $EVAL_ERROR->code() if (isException(\$EVAL_ERROR)); # Else output the unhandled error print $EVAL_ERROR; exit ERROR_UNHANDLED; }; # It shouldn't be possible to get here &log(ASSERT, 'execution reached invalid location in ' . __FILE__ . ', line ' . __LINE__); exit ERROR_ASSERT;