From 1b0256d6ce907223a01506c822b145b13aab1a9a Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 4 Apr 2022 14:19:53 -0400 Subject: [PATCH] Abandon automation of binary packaging for now --- RoboFile.php | 180 ++++++++++++++++++++------------------------------- 1 file changed, 71 insertions(+), 109 deletions(-) diff --git a/RoboFile.php b/RoboFile.php index 973d943..4010e87 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -187,7 +187,10 @@ class RoboFile extends \Robo\Tasks { } // establish which commit to package [$commit, $version] = $this->commitVersion($commit); - $archVersion = preg_replace('/^([^-]+)-(\d+)-(\w+)$/', "$1.r$2.$3", $version); + preg_match('/^([^-]+)(?:-(\d+)-(\w+))?$/', $version, $m); + $archVersion = $m[1].($m[2] ? ".r$m[2].$m[3]" : ""); + $baseVersion = $m[1]; + $release = $m[2]; // name the generic release tarball $tarball = BASE."release/$version/arsse-$version.tar.gz"; // start a collection @@ -200,22 +203,37 @@ class RoboFile extends \Robo\Tasks { return $result; } try { - if (file_exists($dir."dist/debian")) { - // generate the Debian changelog; this also validates our original changelog - $debianChangelog = $this->changelogDebian($this->changelogParse(file_get_contents($dir."CHANGELOG"), $version), $version); - // save the Debian-format changelog - $t->addTask($this->taskWriteToFile($dir."dist/debian/changelog")->text($debianChangelog)); - } + // Perform Arch-specific tasks if (file_exists($dir."dist/arch")) { // patch the Arch PKGBUILD file with the correct version string $t->addTask($this->taskReplaceInFile($dir."dist/arch/PKGBUILD")->regex('/^pkgver=.*$/m')->to("pkgver=$archVersion")); // patch the Arch PKGBUILD file with the correct source file $t->addTask($this->taskReplaceInFile($dir."dist/arch/PKGBUILD")->regex('/^source=\("arsse-[^"]+"\)$/m')->to('source=("'.basename($tarball).'")')); } + // perform Debian-specific tasks + if (file_exists($dir."dist/debian")) { + // generate the Debian changelog; this also validates our original changelog + $changelog = $this->changelogParse(file_get_contents($dir."CHANGELOG"), $version); + $debianChangelog = $this->changelogDebian($changelog, $version); + // save the Debian-format changelog + $t->addTask($this->taskWriteToFile($dir."dist/debian/changelog")->text($debianChangelog)); + } + // perform RPM-specific tasks + if (file_exists($dir."dist/rpm")) { + // patch the spec file with the correct version and release + $t->addTask($this->taskReplaceInFile($dir."dist/rpm/arsse.spec")->regex('/^Version: .*$/m')->to("Version: $baseVersion")); + $t->addTask($this->taskReplaceInFile($dir."dist/rpm/arsse.spec")->regex('/^Release: .*$/m')->to("Release: $release")); + // patch the spec file with the correct tarball name + $t->addTask($this->taskReplaceInFile($dir."dist/rpm/arsse.spec")->regex('/^Source0: .*$/m')->to("Source0: arsse-$version.tar.gz")); + // append the RPM changelog to the spec file + $t->addTask($this->taskWriteToFile($dir."dist/rpm/arsse.spec")->append(true)->text("\n\n%changelog\n".$this->changelogRPM($changelog, $version))); + } // save commit description to VERSION file for reference $t->addTask($this->taskWriteToFile($dir."VERSION")->text($version)); - // perform Composer installation in the temp location with dev dependencies - $t->addTask($this->taskComposerInstall()->arg("-q")->dir($dir)); + if (file_exists($dir."docs") || file_exists($dir."manpages")) { + // perform Composer installation in the temp location with dev dependencies to include Robo and Daux + $t->addTask($this->taskExec("composer install")->arg("-q")->dir($dir)); + } if (file_exists($dir."manpages")) { // generate manpages $t->addTask($this->taskExec("./robo manpage")->dir($dir)); @@ -225,7 +243,7 @@ class RoboFile extends \Robo\Tasks { $t->addTask($this->taskExec("./robo manual -q")->dir($dir)); } // perform Composer installation in the temp location for final output - $t->addTask($this->taskComposerInstall()->dir($dir)->noDev()->optimizeAutoloader()->arg("--no-scripts")->arg("-q")); + $t->addTask($this->taskExec("composer install")->dir($dir)->arg("--no-dev")->arg("-o")->arg("--no-scripts")->arg("-q")); // delete unwanted files $t->addTask($this->taskFilesystemStack()->remove([ $dir.".git", @@ -277,79 +295,6 @@ class RoboFile extends \Robo\Tasks { return $result; } - /** Packages a given commit of the software into an Arch package - * - * The commit to package may be any Git tree-ish identifier: a tag, a branch, - * or any commit hash. If none is provided on the command line, Robo will prompt - * for a commit to package; the default is "HEAD". - * - * The Arch base-devel group should be installed for this. - */ - public function packageArch(string $commit = null): Result { - if (!$this->toolExists("git", "makepkg", "updpkgsums")) { - throw new \Exception("Git, makepkg, and updpkgsums are required in PATH to produce Arch packages"); - } - // establish which commit to package - [$commit, $version] = $this->commitVersion($commit); - $tarball = BASE."release/$version/arsse-$version.tar.gz"; - $dir = dirname($tarball).\DIRECTORY_SEPARATOR; - // start a collection - $t = $this->collectionBuilder(); - // build the generic release tarball if it doesn't exist - if (!file_exists($tarball)) { - $t->addTask($this->taskExec(BASE."robo package:generic $commit")); - } - // extract the PKGBUILD from the tarball - $t->addCode(function() use ($tarball, $dir) { - // because Robo doesn't support extracting a single file we have to do it ourselves - (new \Archive_Tar($tarball))->extractList("arsse/dist/arch/PKGBUILD", $dir, "arsse/dist/arch/", false); - // perform a do-nothing filesystem operation since we need a Robo task result - return $this->taskFilesystemStack()->chmod($dir."PKGBUILD", 0644)->run(); - })->completion($this->taskFilesystemStack()->remove($dir."PKGBUILD")); - // build the package - $t->addTask($this->taskExec("makepkg -Ccf")->dir($dir)); - return $t->run(); - } - - /** Packages a given commit of the software a binary Debian package - * - * The commit to package may be any Git tree-ish identifier: a tag, a branch, - * or any commit hash. If none is provided on the command line, Robo will prompt - * for a commit to package; the default is "HEAD". - * - * The pbuilder tool should be installed for this. - */ - public function packageDeb(string $commit = null): Result { - if (!$this->toolExists("git", "sudo", "pbuilder")) { - throw new \Exception("Git, sudo, and pbuilder are required in PATH to produce Debian packages"); - } - // establish which commit to package - [$commit, $version] = $this->commitVersion($commit); - $tarball = BASE."release/$version/arsse-$version.tar.gz"; - // define some more variables - $tgz = BASE."release/pbuilder-arsse.tgz"; - $bind = dirname($tarball); - $script = BASE."dist/debian/pbuilder.sh"; - $user = trim(`id -un`); - $group = trim(`id -gn`); - // start a task collection - $t = $this->collectionBuilder(); - // check that the pbuilder base exists and create it if it does not - if (!file_exists($tgz)) { - $t->addTask($this->taskFilesystemStack()->mkdir(BASE."release")); - $t->addTask($this->taskExec('sudo pbuilder create --basetgz '.escapeshellarg($tgz).' --mirror http://ftp.ca.debian.org/debian/ --extrapackages "debhelper devscripts lintian"')); - } - // build the generic release tarball if it doesn't exist - if (!file_exists($tarball)) { - $t->addTask($this->taskExec(BASE."robo package:generic $commit")); - } - // build the packages - $t->addTask($this->taskExec('sudo pbuilder execute --basetgz '.escapeshellarg($tgz).' --bindmounts '.escapeshellarg($bind).' -- '.escapeshellarg($script).' '.escapeshellarg("$bind/".basename($tarball)))); - // take ownership of the output files - $t->addTask($this->taskExec("sudo chown -R $user:$group ".escapeshellarg($bind))); - return $t->run(); - } - /** Packages a release tarball into a Debian source package * * The commit to package may be any Git tree-ish identifier: a tag, a branch, @@ -381,7 +326,7 @@ class RoboFile extends \Robo\Tasks { // re-pack the tarball using a specific name special to Debian $t->addTask($this->taskPack($dir."arsse_$baseVersion.orig.tar.gz")->addDir("arsse-$baseVersion", $base)); // pack the debian tarball - $t->addTask($this->taskPack($dir."arsse_$debVersion.debian.tar.gz")->addDir("debian", $base."dist")); + $t->addTask($this->taskPack($dir."arsse_$debVersion.debian.tar.gz")->addDir("debian", $base."dist/debian")); // generate the DSC file $t->addCode(function() use ($t, $debVersion, $baseVersion, $dir, $base) { try { @@ -393,49 +338,66 @@ class RoboFile extends \Robo\Tasks { return $this->taskWriteToFile($dir."arsse_$debVersion.dsc")->text($dsc)->run(); }); // delete any existing files - $t->AddTask($this->taskFilesystemStack()->remove(BASE."release/$version/arsse_$baseVersion.orig.tar.gz")->remove(BASE."release/$version/arsse_$debVersion.debian.tar.gz")->remove(BASE."release/$version/arsse_$debVersion.dsc")); + $t->AddTask($this->taskFilesystemStack()->remove([BASE."release/$version/arsse_$baseVersion.orig.tar.gz", BASE."release/$version/arsse_$debVersion.debian.tar.gz", BASE."release/$version/arsse_$debVersion.dsc"])); + // copy the new files over $t->addTask($this->taskFilesystemStack()->copy($dir."arsse_$baseVersion.orig.tar.gz", BASE."release/$version/arsse_$baseVersion.orig.tar.gz")->copy($dir."arsse_$debVersion.debian.tar.gz", BASE."release/$version/arsse_$debVersion.debian.tar.gz")->copy($dir."arsse_$debVersion.dsc", BASE."release/$version/arsse_$debVersion.dsc")); return $t->run(); } - /** Generates all possible package types for a given commit of the software + /** Packages a given commit of the software and produces all relevant release files * * The commit to package may be any Git tree-ish identifier: a tag, a branch, * or any commit hash. If none is provided on the command line, Robo will prompt * for a commit to package; the default is "HEAD". * - * Generic release tarballs will always be generated, but distribution-specific - * packages are skipped when the required tools are not available + * In addition to the release tarball, a Debian source package, Arch PKGBUILD, + * and RPM spec file are output as well. These are suitable for use with Open + * Build Service instances and with slight modification the Arch User Repository. + * Use for Launchpad PPAs has not been tested. */ public function package(string $commit = null): Result { if (!$this->toolExists("git")) { throw new \Exception("Git is required in PATH to produce packages"); } - [$commit,] = $this->commitVersion($commit); - // determine whether the distribution-specific packages can be built - $dist = [ - 'Arch' => $this->toolExists("git", "makepkg", "updpkgsums"), - 'Deb' => $this->toolExists("git", "sudo", "pbuilder"), - ]; + [$commit, $version] = $this->commitVersion($commit); + $tarball = BASE."release/$version/arsse-$version.tar.gz"; + // build the generic release tarball + $result = $this->taskExec(BASE."robo package:generic $commit")->run(); + if (!$result->wasSuccessful()) { + return $result; + } + // if the generic tarball could be built, try to produce Arch, Debian, and RPM files; these might legitimately not exist in old releases + // start by getting the list of files from the tarball + $archive = new \Archive_Tar($tarball); + $filelist = array_flip(array_column($archive->listContent(), "filename")); // start a collection $t = $this->collectionBuilder(); - // build the generic release tarball - $t->addTask($this->taskExec(BASE."robo package:generic $commit")); - // build other packages - foreach ($dist as $distro => $run) { - if ($run) { - $subcmd = strtolower($distro); - $t->addTask($this->taskExec(BASE."robo package:$subcmd $commit")); - } + // Produce an Arch PKGBUILD if appropriate + if (isset($filelist['arsse/dist/arch/PKGBUILD'])) { + $t->addCode(function() use ($tarball, $archive) { + $dir = dirname($tarball).\DIRECTORY_SEPARATOR; + $archive->extractList("arsse/dist/arch/PKGBUILD", $dir, "arsse/dist/arch/", false); + // update the tarball's checksum + $sums = [ + 'md5' => hash_file("md5", $tarball), + ]; + return $this->taskReplaceInFile($dir."PKGBUILD")->regex('/^md5sums=\("SKIP"\)$/m')->to('md5sums=("'.$sums['md5'].'")')->run(); + }); } - $out = $t->run(); - // note any packages which were not built - foreach ($dist as $distro => $run) { - if (!$run) { - $this->say("Packages for $distro skipped"); - } + // Produce a Debian source package if appropriate + if (isset($filelist['arsse/dist/debian/control']) && isset($filelist['arsse/dist/debian/source/format'])) { + $t->addTask($this->taskExec(BASE."robo package:debsrc $commit")); + } + // Produce an RPM spec file if appropriate + if (isset($filelist['arsse/dist/rpm/arsse.spec'])) { + $t->addCode(function() use ($tarball, $archive) { + $dir = dirname($tarball).\DIRECTORY_SEPARATOR; + $archive->extractList("arsse/dist/rpm/arsse.spec", $dir, "arsse/dist/rpm/", false); + // perform a do-nothing filesystem operation since we need a Robo task result + return $this->taskFilesystemStack()->chmod($dir."arsse.spec", 0644)->run(); + }); } - return $out; + return $t->run(); } /** Generates static manual pages in the "manual" directory