Remove the obsolete build-package script, and the scripts for the release process and lab testing (which are now maintained separately at https://codeberg.org/ivarch/scripts), and add a release config file for the new release script under the same location.
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@ bin_PROGRAMS = pv
|
||||
dist_doc_DATA = README.md docs/INSTALL docs/COPYING docs/NEWS.md docs/ACKNOWLEDGEMENTS.md docs/DEVELOPERS.md
|
||||
dist_man1_MANS = docs/pv.1
|
||||
|
||||
EXTRA_DIST = docs/pv.1.md docs/benchmark.sh docs/test-on-vm-lab.sh docs/build-package.sh docs/release.sh
|
||||
EXTRA_DIST = docs/pv.1.md docs/benchmark.sh docs/release.cf
|
||||
|
||||
pv_SOURCES = \
|
||||
src/main/debug.c \
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Usage: sh build-package.sh source-1.2.3.tar.gz
|
||||
#
|
||||
# Given a tar.gz, build a package for the current OS.
|
||||
#
|
||||
# Supports these packaging types:
|
||||
#
|
||||
# .deb (Debian, Ubuntu, etc) - requires dpkg-dev, debhelper
|
||||
# .rpm (AlmaLinux, Rocky Linux, OpenSUSE etc) - requires rpmbuild
|
||||
#
|
||||
# If the MAINTAINER environment variable is set, this is used as a GPG key
|
||||
# ID for package signing.
|
||||
#
|
||||
# The packages built with this script are not "official", in that they are
|
||||
# not part of any Linux distribution and may not follow the distribution's
|
||||
# policies. Use at your own risk.
|
||||
#
|
||||
# Copyright 2024-2025 Andrew Wood
|
||||
# License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
sourceArchive="$1"
|
||||
test -n "${sourceArchive}" && test -f "${sourceArchive}" \
|
||||
|| { printf "%s: %s: %s\n" "${0##*/}" "${sourceArchive}" "source archive not found" 1>&2; exit 1; }
|
||||
|
||||
packageName="pv"
|
||||
packageSummary="Shell pipeline element to meter data passing through"
|
||||
packageDescription="\
|
||||
pv (Pipe Viewer) can be inserted into any normal pipeline between two
|
||||
processes to give a visual indication of how quickly data is passing
|
||||
through, how long it has taken, how near to completion it is, and an
|
||||
estimate of how long it will be until completion."
|
||||
packageUrl="https://ivarch.com/p/pv"
|
||||
sourceUrl="https://ivarch.com/programs/sources/${packageName}-%{version}.tar.gz"
|
||||
packageEmail="Andrew Wood <pv@ivarch.com>"
|
||||
|
||||
workDir="$(mktemp -d)" || exit 1
|
||||
trap 'rm -rf "${workDir}"' EXIT
|
||||
|
||||
# Infer the version from the most recent NEWS entry.
|
||||
version="$(tar xzf "${sourceArchive}" --wildcards -O '*/docs/NEWS.md' 2>/dev/null | awk '/^### [0-9]/{print $2}' | sed -n 1p)"
|
||||
|
||||
if command -v rpmbuild >/dev/null 2>&1; then
|
||||
# Build an RPM.
|
||||
cat > "${workDir}"/spec <<EOF
|
||||
Summary: ${packageSummary}
|
||||
Name: ${packageName}
|
||||
Version: ${version}
|
||||
Release: 1%{?dist}
|
||||
License: GPLv3+
|
||||
Source: ${sourceUrl}
|
||||
Url: ${packageUrl}
|
||||
|
||||
%description
|
||||
${packageDescription}
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
%configure
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
test -n "\${RPM_BUILD_ROOT}" && test "\${RPM_BUILD_ROOT}" != '/' && rm -rf "\${RPM_BUILD_ROOT}"
|
||||
make install DESTDIR="\${RPM_BUILD_ROOT}"
|
||||
rm -rf "\${RPM_BUILD_ROOT}/usr/share/doc"
|
||||
%find_lang %{name}
|
||||
|
||||
%check
|
||||
make check SKIP_VALGRIND_TESTS=1
|
||||
|
||||
%clean
|
||||
test -n "\${RPM_BUILD_ROOT}" && test "\${RPM_BUILD_ROOT}" != '/' && rm -rf "\${RPM_BUILD_ROOT}"
|
||||
|
||||
%files -f %{name}.lang
|
||||
%defattr(-, root, root)
|
||||
%{_bindir}/*
|
||||
%{_mandir}/man1/*
|
||||
|
||||
%doc README.md docs/NEWS.md docs/ACKNOWLEDGEMENTS.md docs/COPYING
|
||||
|
||||
%changelog
|
||||
* $(date '+%a %b %d %Y') ${packageEmail} - ${version}-1
|
||||
- Package built from main source.
|
||||
EOF
|
||||
mkdir "${workDir}/SOURCES"
|
||||
cp "${sourceArchive}" "${workDir}/SOURCES/${packageName}-${version}.tar.gz"
|
||||
rpmbuild -D "%_topdir ${workDir}" -bb "${workDir}/spec" || exit 1
|
||||
if test -n "${MAINTAINER}"; then
|
||||
# Sign the RPMs.
|
||||
rpm -D "%_gpg_name ${MAINTAINER}" --addsign "${workDir}/RPMS"/*/*.rpm || exit 1
|
||||
fi
|
||||
cp -v "${workDir}/RPMS"/*/*.rpm .
|
||||
fi
|
||||
|
||||
if command -v dpkg-buildpackage >/dev/null 2>&1; then
|
||||
# Build a Debian package.
|
||||
mkdir "${workDir}/build" "${workDir}/build/debian" "${workDir}/build/debian/source"
|
||||
|
||||
tar xzf "${sourceArchive}" -C "${workDir}/build" --strip-components=1
|
||||
|
||||
printf "%s\n" "10" > "${workDir}/build/debian/compat"
|
||||
touch "${workDir}/build/debian/copyright"
|
||||
printf "%s\n" "3.0 (quilt)" > "${workDir}/build/debian/source/format"
|
||||
|
||||
cat > "${workDir}/build/debian/rules" <<EOF
|
||||
#!/usr/bin/make -f
|
||||
export DH_VERBOSE = 1
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
||||
|
||||
%:
|
||||
dh \$@
|
||||
EOF
|
||||
chmod 700 "${workDir}/build/debian/rules"
|
||||
|
||||
cat > "${workDir}/build/debian/control" <<EOF
|
||||
Source: ${packageName}
|
||||
Maintainer: ${packageEmail}
|
||||
Section: misc
|
||||
Priority: optional
|
||||
Standards-Version: 3.9.2
|
||||
Build-Depends: debhelper (>= 9)
|
||||
|
||||
Package: ${packageName}
|
||||
Architecture: any
|
||||
Depends: \${misc:Depends}
|
||||
Description: ${packageSummary}
|
||||
$(printf "%s\n.\n" "${packageDescription}" | sed 's,^, ,')
|
||||
EOF
|
||||
|
||||
cat > "${workDir}/build/debian/changelog" <<EOF
|
||||
${packageName} (${version}-1) UNRELEASED; urgency=low
|
||||
|
||||
* Package built from main source.
|
||||
|
||||
-- ${packageEmail} $(date -R)
|
||||
EOF
|
||||
|
||||
if test -n "${MAINTAINER}"; then
|
||||
(cd "${workDir}/build" && dpkg-buildpackage --build=binary --force-sign --sign-key="${MAINTAINER}") || exit 1
|
||||
else
|
||||
(cd "${workDir}/build" && dpkg-buildpackage --build=binary) || exit 1
|
||||
fi
|
||||
|
||||
cp -v "${workDir}"/*.deb . || exit 1
|
||||
fi
|
||||
@@ -0,0 +1,51 @@
|
||||
# Configuration for the foss-release.sh script.
|
||||
# The script is here: https://codeberg.org/ivarch/scripts
|
||||
|
||||
set maintainer andrew.wood@ivarch.com
|
||||
set mainprogram auto
|
||||
set version auto
|
||||
set mandir docs
|
||||
set newsdir docs
|
||||
|
||||
export SKIP_VALGRIND_TESTS=1
|
||||
|
||||
section Initial checks
|
||||
action check_po
|
||||
action check_version_news
|
||||
action check_version_autoconf
|
||||
action check_version_man
|
||||
|
||||
section Initial build
|
||||
action configure
|
||||
action make
|
||||
action check_analyse
|
||||
action check_version_program
|
||||
action check_version_year
|
||||
|
||||
section Documentation and source reformatting
|
||||
action man_md
|
||||
action man_html
|
||||
action news_html
|
||||
action make_indent
|
||||
|
||||
section Update po files
|
||||
action make_update_po
|
||||
|
||||
section Run autoreconf
|
||||
action autoreconf
|
||||
|
||||
section Commit check
|
||||
action check_git_status
|
||||
|
||||
section Release archive
|
||||
action check_make_distcheck
|
||||
action make_dist
|
||||
|
||||
section Lab tests
|
||||
action labtest
|
||||
|
||||
section Sign release
|
||||
action sign_tarball
|
||||
|
||||
section Build OS packages
|
||||
action parmo_build
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Automate a portion of the release checklist. Expects to be run from a
|
||||
# build directory, such as one in which "configure" has been run, i.e.
|
||||
# there should be a Makefile present.
|
||||
#
|
||||
# Requires "parmo" (https://ivarch.com/p/parmo); builds for all targets that
|
||||
# parmo supports.
|
||||
#
|
||||
# All of the release artefacts are placed in a "PV-RELEASE-x" directory,
|
||||
# where "x" is the version.
|
||||
#
|
||||
# Copyright 2024-2025 Andrew Wood
|
||||
# License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
srcdir="$(awk '/^VPATH/{print $NF}' < Makefile | sed -n 1p)"
|
||||
manuals="$(find "${srcdir}/docs" -mindepth 1 -maxdepth 1 -type f -name "*.[0-9]" -printf "%f\n")"
|
||||
mainProgram="$(awk '/^[a-z]+_PROGRAMS/{print $3}' Makefile |cut -d '$' -f 1 | sed -n 1p)"
|
||||
labTestScript="${srcdir}/docs/test-on-vm-lab.sh"
|
||||
|
||||
status () {
|
||||
test -n "$*" && printf "\n"
|
||||
printf '\e]0;%s\007\r' "$*" >&2
|
||||
if test -n "$*"; then
|
||||
tput rev >&2
|
||||
printf " -- %s -- " "$*" >&2
|
||||
tput sgr0 >&2
|
||||
printf "\n\n"
|
||||
fi
|
||||
}
|
||||
|
||||
possiblyDie () {
|
||||
printf "\n" >&2
|
||||
tput bold >&2
|
||||
printf "%s: %s\n" "release" "$*" >&2
|
||||
tput sgr0 >&2
|
||||
printf "\n%s\n" "Type 'y' and hit Enter to continue anyway."
|
||||
read -r line
|
||||
test "${line}" = "y" || { status ""; exit 1; }
|
||||
}
|
||||
|
||||
test -e "${labTestScript}" || labTestScript=""
|
||||
|
||||
# The checklist is re-ordered a little so that we defer making changes (like
|
||||
# "make indent") until as late as possible, in case any checks fail.
|
||||
|
||||
status "Initial checks"
|
||||
|
||||
# Check MAINTAINER is provided.
|
||||
test -n "${MAINTAINER}" || possiblyDie "environment variable MAINTAINER is empty"
|
||||
|
||||
# * Check that _po/POTFILES.in_ is up to date
|
||||
if test -d "${srcdir}/po"; then
|
||||
inFile="$(sort < "${srcdir}/po/POTFILES.in")"
|
||||
realList="$(find "${srcdir}" -name "*.c" -printf "%P\n" | sort)"
|
||||
test "${inFile}" = "${realList}" || possiblyDie "po/POTFILES.in is incorrect"
|
||||
fi
|
||||
|
||||
status "Initial build"
|
||||
make || possiblyDie "failed 'make'"
|
||||
|
||||
# * Run "_make analyse_" and see whether remaining warnings can be addressed
|
||||
status "Source analysis"
|
||||
make analyse || possiblyDie "failed 'make analyse'"
|
||||
|
||||
# * Version bump and documentation checks:
|
||||
|
||||
status "Version checks"
|
||||
|
||||
# * Check that _docs/NEWS.md_ is up to date
|
||||
sed -n 1p docs/NEWS.md | grep -Fqi unreleased && possiblyDie "NEWS.md says 'unreleased' on line 1"
|
||||
versionInNews="$(awk 'FNR==1{print $2}' "${srcdir}/docs/NEWS.md")"
|
||||
printf "%s\n" "${versionInNews}" | grep -Eq '^[0-9]' || possiblyDie "version in NEWS.md (${versionInNews}) is not numeric"
|
||||
|
||||
# * Check the version in both _configure.ac_ and _docs/NEWS.md_ was updated
|
||||
versionInConfig="$(grep ^AC_INIT "${srcdir}/configure.ac" | cut -d '[' -f 3 | cut -d ']' -f 1)"
|
||||
test "${versionInConfig}" = "${versionInNews}" || possiblyDie "version in configure.ac (${versionInConfig}) mismatches NEWS.md (${versionInNews})"
|
||||
|
||||
# * Check that the manuals are up to date
|
||||
for manPage in ${manuals}; do
|
||||
versionInManual="$(awk 'FNR==1 {print $5}' "${srcdir}/docs/${manPage}" | cut -d - -f 2)"
|
||||
test "${versionInManual}" = "${versionInNews}" || possiblyDie "version in ${manPage} (${versionInManual}) mismatches NEWS.md (${versionInNews})"
|
||||
done
|
||||
|
||||
# * Check that the program version is correct
|
||||
versionInVersionOutput="$(./"${mainProgram}" --version | awk 'FNR==1{print $NF}')"
|
||||
test "${versionInVersionOutput}" = "${versionInNews}" || possiblyDie "version in '${mainProgram} --version' (${versionInVersionOutput}) mismatches NEWS.md (${versionInNews})"
|
||||
|
||||
# * Check that the year displayed by --version is correct
|
||||
yearInVersion="$(./"${mainProgram}" --version | awk '/^Copyright/{print $2}')"
|
||||
yearNow="$(date '+%Y')"
|
||||
test "${yearInVersion}" = "${yearNow}" || possiblyDie "the year in '--version' (${yearInVersion}) is not this year (${yearNow})"
|
||||
|
||||
# * Make the Markdown version of the manuals and, if using VPATH, copy the result to the source directory
|
||||
# We also wipe everything in "docs" so we don't accidentally package
|
||||
# leftover working files.
|
||||
|
||||
status "Markdown manual"
|
||||
|
||||
rm -f docs/*
|
||||
for manPage in ${manuals}; do
|
||||
make "docs/${manPage}.md"
|
||||
cp "docs/${manPage}.md" "${srcdir}/docs/${manPage}.md"
|
||||
done
|
||||
|
||||
# * Run "_make indent; make indent indentclean check_"
|
||||
status "Reformat source"
|
||||
make indent
|
||||
make indent indentclean
|
||||
# The check will run later as part of "make distcheck".
|
||||
|
||||
# * Run "_make -C po update-po_"
|
||||
status "Update po files"
|
||||
if test -d "${srcdir}/po"; then
|
||||
make -C po update-po || possiblyDie "update-po failed"
|
||||
fi
|
||||
|
||||
# * Run "_autoreconf_" in the source directory
|
||||
status "Run autoreconf"
|
||||
(cd "${srcdir}" && autoreconf -is) || possiblyDie "autoreconf failed"
|
||||
|
||||
# * Ensure everything has been committed to the repository
|
||||
status "Commit check"
|
||||
gitStatus="$(cd "${srcdir}" && git status --porcelain=v1)" || possiblyDie "failed to run 'git status'"
|
||||
test -z "${gitStatus}" || possiblyDie "not everything is committed - 'git status' is not empty"
|
||||
|
||||
# * Consistency and build checks:
|
||||
# * Wipe the build directory, and run "_configure_" there
|
||||
# * Run "_make distcheck_"
|
||||
# * Run "_make release MAINTAINER=<signing-user>_"
|
||||
# NB "make release" implies "make distcheck".
|
||||
# We set SKIP_VALGRIND_TESTS=1 because the full tests will run in the lab
|
||||
# check.
|
||||
status "Release archive"
|
||||
workDir="$(mktemp -d)" || possiblyDie "mktemp failed"
|
||||
trap 'chmod -R u+w "${workDir}"; rm -rf "${workDir}"' EXIT
|
||||
(
|
||||
cd "${workDir}" || exit 1
|
||||
sh "${srcdir}/configure" || exit 1
|
||||
make -j8 release SKIP_VALGRIND_TESTS=1 || exit 1
|
||||
exit 0
|
||||
) || possiblyDie "failed on 'make release'"
|
||||
|
||||
sourceArchive="$(find "${workDir}" -mindepth 1 -maxdepth 1 -type f -name "*.tar.gz")"
|
||||
test -e "${sourceArchive}.asc" || possiblyDie "release was not signed"
|
||||
|
||||
# * Run "_./configure && make check_" on all test systems, using the _tar.gz_ that was just created
|
||||
# * Run a cross-compilation check
|
||||
if test -n "${labTestScript}"; then
|
||||
status "Lab test"
|
||||
sh "${labTestScript}" "${sourceArchive}" || possiblyDie "lab test failed"
|
||||
fi
|
||||
|
||||
# * Update the project web site:
|
||||
# * Copy the release _.tar.gz_, _.txt_, and _.asc_ files to the web site
|
||||
# * Use "_pandoc --from markdown --to html_" to convert the news and manual to HTML
|
||||
status "Release dir"
|
||||
releaseDir="PV-RELEASE-${versionInNews}"
|
||||
rm -rf "${releaseDir}"
|
||||
mkdir "${releaseDir}"
|
||||
cp "${sourceArchive}" "${sourceArchive}.asc" "${sourceArchive}.txt" "${releaseDir}/" || possiblyDie "failed to copy release files"
|
||||
|
||||
status "HTML docs"
|
||||
for manPage in ${manuals}; do
|
||||
pandoc --from markdown --to html --shift-heading-level-by=1 < "${srcdir}/docs/${manPage}.md" > "${releaseDir}/${manPage}.html"
|
||||
done
|
||||
pandoc --from markdown --to html < "${srcdir}/docs/NEWS.md" > "${releaseDir}/news.html"
|
||||
|
||||
# Build OS packages.
|
||||
buildTargets=$(parmo targets)
|
||||
if test -n "${MAINTAINER}"; then
|
||||
gpg --export-secret-key --armor "${MAINTAINER}" > "${workDir}/signing-key" \
|
||||
|| possiblyDie 'failed to export signing key'
|
||||
fi
|
||||
for buildTarget in ${buildTargets}; do
|
||||
status "Package: ${buildTarget}"
|
||||
buildOK=true
|
||||
rm -rf "${workDir}/package"
|
||||
mkdir "${workDir}/package"
|
||||
if test -s "${workDir}/signing-key"; then
|
||||
parmo --key "${workDir}/signing-key" --source "${sourceArchive}" --destination "${workDir}/package" --target "${buildTarget}" build-package \
|
||||
|| possiblyDie "${buildTarget}: build failed"
|
||||
else
|
||||
parmo --source "${sourceArchive}" --destination "${workDir}/package" --target "${buildTarget}" build-package \
|
||||
|| possiblyDie "${buildTarget}: build failed"
|
||||
fi
|
||||
find "${workDir}/package" -type f \
|
||||
| while read -r packageFile; do
|
||||
destinationFile="${releaseDir}/${packageFile##*/}"
|
||||
case "${destinationFile}" in
|
||||
*.deb) destinationFile="${destinationFile%.deb}_${buildTarget}.deb" ;;
|
||||
*.txt) destinationFile="" ;;
|
||||
esac
|
||||
test -n "${destinationFile}" || continue
|
||||
cp "${packageFile}" "${destinationFile}"
|
||||
chmod 644 "${destinationFile}"
|
||||
done
|
||||
done
|
||||
|
||||
find "${releaseDir}/" -type f -exec chmod 644 '{}' ';'
|
||||
find "${releaseDir}/" -type d -exec chmod 755 '{}' ';'
|
||||
|
||||
status "Done"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Files are under: ${releaseDir}/
|
||||
|
||||
Still to do:
|
||||
* Update the news and manual on the web site
|
||||
* Update the version numbers on the web site
|
||||
* Update the package index on the web site
|
||||
* Create a new release in the repository, and apply the associated tag
|
||||
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
@@ -1,343 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run "make check" from a source tarball, on a whole lab of VMs.
|
||||
#
|
||||
# The source tarball should contain a directory; this directory must contain
|
||||
# a "configure" script. After running "configure", this script calls "make"
|
||||
# and then "make check", from a build subdirectory.
|
||||
#
|
||||
# Hostnames need to be listed on the command line after the tarball, or in
|
||||
# ~/.config/lab-hosts. They need to be reachable over SSH with no password.
|
||||
#
|
||||
# Cross-compilation is performed if the hostname is of the form "x:y", where
|
||||
# "x" is a target like "arm-linux-gnueabi", and "y" is the name of a host of
|
||||
# that architecture. The package is built locally with "--host=x" and the
|
||||
# result is copied to "y" and "make check" is run.
|
||||
#
|
||||
# Displays progress to the terminal and produces a tarball of results. In
|
||||
# the results, the file "latest-status.txt" contains the last status
|
||||
# display, and there is a directory for each host. The directories contain
|
||||
# SCW metrics files plus "output.log" (timestamped), "raw-output.log"
|
||||
# (without timestamps), "framework-output.log" (messages from this script),
|
||||
# and the "config.log", "test-suite.log", and "tests/" from the build area.
|
||||
#
|
||||
# Requires "scw" (https://ivarch.com/p/scw).
|
||||
#
|
||||
# Copyright 2024-2025 Andrew Wood
|
||||
# License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
#
|
||||
# Version: 0.0.1 / 16 Dec 2024
|
||||
|
||||
# Number of tests to run in parallel on each host.
|
||||
concurrency="1"
|
||||
|
||||
# Run a build and check, according to these environment variables:
|
||||
#
|
||||
# sourceArchive local source tarball path
|
||||
# buildHost where to build, or "" for local
|
||||
# checkHost where to test, or "" for local
|
||||
# remoteBuildDir temp directory for remote build or check
|
||||
# localBuildDir temp directory for local build
|
||||
# configureArguments extra "configure" script arguments
|
||||
#
|
||||
# Does not return - always exits.
|
||||
#
|
||||
# Expects to be run under SCW, so writes status to fd 3.
|
||||
#
|
||||
testRunner () {
|
||||
printf '%s %s\n' 'notice' 'creating build area' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" mkdir "${remoteBuildDir}" || exit 1
|
||||
else
|
||||
mkdir "${localBuildDir}" || exit 1
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'created build area' >&3
|
||||
|
||||
if test -n "${checkHost}"; then
|
||||
printf '%s %s\n' 'notice' 'creating check area' >&3
|
||||
ssh "${checkHost}" mkdir "${remoteBuildDir}" || exit 1
|
||||
printf '%s %s\n' 'ok' 'created check area' >&3
|
||||
fi
|
||||
|
||||
printf '%s %s\n' 'notice' 'copying source archive' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
scp "${sourceArchive}" "${buildHost}:${remoteBuildDir}/" || exit 1
|
||||
elif test -n "${checkHost}"; then
|
||||
scp "${sourceArchive}" "${checkHost}:${remoteBuildDir}/" || exit 1
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'source archive copied' >&3
|
||||
|
||||
printf '%s %s\n' 'notice' 'extracting source archive' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" tar xzf "${remoteBuildDir}/${sourceArchive##*/}" -C "${remoteBuildDir}" || exit $?
|
||||
else
|
||||
tar xzf "${sourceArchive}" -C "${localBuildDir}" || exit $?
|
||||
ssh "${checkHost}" tar xzf "${remoteBuildDir}/${sourceArchive##*/}" -C "${remoteBuildDir}" || exit $?
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'source archive extracted' >&3
|
||||
|
||||
stepResult="ok"
|
||||
if test -n "${buildHost}"; then
|
||||
printf '%s %s\n' 'notice' 'configuring' >&3
|
||||
ssh "${buildHost}" "cd \"${remoteBuildDir}\" && mkdir BUILD && cd BUILD && ../*/configure ${configureArguments}" || exit $?
|
||||
else
|
||||
printf '%s %s\n' 'notice' 'configuring locally' >&3
|
||||
( cd "${localBuildDir}" && mkdir BUILD && cd BUILD && ../*/configure ${configureArguments} ) || exit $?
|
||||
printf '%s %s\n' 'notice' "configuring on ${checkHost}" >&3
|
||||
ssh "${checkHost}" "cd \"${remoteBuildDir}\" && mkdir BUILD && cd BUILD && ../*/configure" \
|
||||
|| { stepResult="warning"; printf '%s %s\n' 'warning' "configuration failed on ${checkHost}" >&3; }
|
||||
fi
|
||||
printf '%s %s\n' "${stepResult}" 'configuration completed' >&3
|
||||
|
||||
printf '%s %s\n' 'notice' 'building' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" "cd \"${remoteBuildDir}/BUILD\" && make -j${concurrency}" || exit $?
|
||||
else
|
||||
make -j${concurrency} -C "${localBuildDir}/BUILD" || exit $?
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'build completed' >&3
|
||||
|
||||
if test -n "${buildHost}"; then
|
||||
printf '%s %s\n' 'notice' 'testing' >&3
|
||||
ssh "${buildHost}" "cd \"${remoteBuildDir}/BUILD\" && make -j${concurrency} check" || exit $?
|
||||
printf '%s %s\n' 'ok' 'testing completed' >&3
|
||||
elif test -n "${checkHost}"; then
|
||||
printf '%s %s\n' 'notice' "transferring build to ${checkHost}" >&3
|
||||
tar cvf "${localBuildDir}/build.tar" -C "${localBuildDir}" BUILD || exit $?
|
||||
scp "${localBuildDir}/build.tar" "${checkHost}:${remoteBuildDir}/build.tar" || exit $?
|
||||
ssh "${checkHost}" "tar xf \"${remoteBuildDir}/build.tar\" -C \"${remoteBuildDir}\"" || exit $?
|
||||
printf '%s %s\n' 'ok' "transferred build to ${checkHost}" >&3
|
||||
printf '%s %s\n' 'notice' "testing on ${checkHost}" >&3
|
||||
ssh "${checkHost}" "cd \"${remoteBuildDir}/BUILD\" && make -j${concurrency} check-TESTS XCTEST=1" || exit $?
|
||||
printf '%s %s\n' 'ok' 'testing completed' >&3
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
# Using directory $1 for metrics and output, run the remaining arguments as
|
||||
# a command using "scw" to capture metrics and record logs.
|
||||
#
|
||||
recordCommand () {
|
||||
targetDir="$1"
|
||||
shift
|
||||
mkdir -p "${targetDir}"
|
||||
scw -c /dev/null \
|
||||
-s UserConfigFile=/dev/null \
|
||||
-s ItemsDir=/dev/null \
|
||||
-s MetricsDir="${targetDir}" \
|
||||
-s CheckLockFile="${targetDir}/.widelock" \
|
||||
-s OutputMap= \
|
||||
-s OutputMap="OES stamped ${targetDir}/output.log" \
|
||||
-s OutputMap="OES raw ${targetDir}/raw-output.log" \
|
||||
-s Command="$*" \
|
||||
run item
|
||||
}
|
||||
|
||||
if test "$1" = "--testRunner"; then
|
||||
testRunner
|
||||
exit 1
|
||||
fi
|
||||
|
||||
labHosts="$(grep -v '^#' ~/.config/lab-hosts 2>/dev/null)"
|
||||
|
||||
workDir=$(mktemp -d) || exit 1
|
||||
trap 'rm -rf "${workDir}"' EXIT
|
||||
|
||||
sourceArchive="$1"
|
||||
shift
|
||||
hostList="$*"
|
||||
test -n "${hostList}" || hostList="${labHosts}"
|
||||
|
||||
test -n "${sourceArchive}" || { echo "Usage: ${0##*/} TARBALL [HOST...]"; exit 1; }
|
||||
test -s "${sourceArchive}" || { echo "${sourceArchive}: not found"; exit 1; }
|
||||
|
||||
attrBold="$(tput bold 2>/dev/null)"
|
||||
attrUnderline="$(tput smul 2>/dev/null)"
|
||||
attrRed="$(tput setaf 1 2>/dev/null)"
|
||||
attrGreen="$(tput setaf 2 2>/dev/null)"
|
||||
attrYellow="$(tput setaf 3 2>/dev/null)"
|
||||
attrBlue="$(tput setaf 4 2>/dev/null)"
|
||||
attrMagenta="$(tput setaf 5 2>/dev/null)"
|
||||
attrCyan="$(tput setaf 6 2>/dev/null)"
|
||||
attrWhite="$(tput setaf 7 2>/dev/null)"
|
||||
attrNone="$(tput sgr0 2>/dev/null)"
|
||||
|
||||
dateStamp="$(date +%Y%m%d-%H%M)"
|
||||
resultsArchive="result-${dateStamp}.tar.gz"
|
||||
|
||||
startEpoch="$(date +%s)"
|
||||
|
||||
|
||||
for hostSpec in ${hostList}; do
|
||||
localTestDir="${workDir}/${hostSpec}"
|
||||
remoteBuildDir="test-${dateStamp}.$(date +%s).$$"
|
||||
buildHost="${hostSpec}"
|
||||
checkHost=""
|
||||
configureArguments=""
|
||||
|
||||
xcFor="${hostSpec%:*}"
|
||||
xcRunOn="${hostSpec#*:}"
|
||||
|
||||
if ! test "${xcFor}" = "${xcRunOn}"; then
|
||||
localTestDir="${workDir}/${xcFor}-${xcRunOn}"
|
||||
buildHost=""
|
||||
checkHost="${xcRunOn}"
|
||||
configureArguments="--host ${xcFor}"
|
||||
fi
|
||||
|
||||
mkdir "${localTestDir}"
|
||||
printf "%s\n" "${hostSpec}" > "${localTestDir}/hostSpec"
|
||||
|
||||
localBuildDir="${localTestDir}/XC"
|
||||
|
||||
(
|
||||
flock -x 3
|
||||
|
||||
export sourceArchive buildHost checkHost remoteBuildDir localBuildDir configureArguments
|
||||
recordCommand "${localTestDir}" "sh \"$0\" --testRunner" 3<&-
|
||||
|
||||
exec >>"${localTestDir}/output.log" 2>&1
|
||||
|
||||
printf '*** %s\n' 'retrieving build and test artefacts'
|
||||
mkdir "${localTestDir}/tests"
|
||||
if test -n "${buildHost}"; then
|
||||
scp "${buildHost}:${remoteBuildDir}/BUILD/config.log" "${localTestDir}/"
|
||||
scp "${buildHost}:${remoteBuildDir}/BUILD/test-suite.log" "${localTestDir}/"
|
||||
scp "${buildHost}:${remoteBuildDir}/BUILD/tests/*" "${localTestDir}/tests/"
|
||||
elif test -n "${checkHost}"; then
|
||||
scp "${checkHost}:${remoteBuildDir}/BUILD/config.log" "${localTestDir}/"
|
||||
scp "${checkHost}:${remoteBuildDir}/BUILD/test-suite.log" "${localTestDir}/"
|
||||
scp "${checkHost}:${remoteBuildDir}/BUILD/tests/*" "${localTestDir}/tests/"
|
||||
fi
|
||||
|
||||
printf '*** %s\n' 'removing build area'
|
||||
rm -rf "${localBuildDir}"
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" rm -rf "${remoteBuildDir}"
|
||||
elif test -n "${checkHost}"; then
|
||||
ssh "${checkHost}" rm -rf "${remoteBuildDir}"
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
|
||||
flock -u 3
|
||||
) > "${localTestDir}/framework-output.log" 2>&1 3>>"${localTestDir}/active" &
|
||||
done
|
||||
|
||||
sleep 0.1
|
||||
|
||||
allTestHostDirs="$(find "${workDir}" -mindepth 1 -maxdepth 1 -name "[0-9A-Za-z_]*" -type d -printf "%f\n" | sort)"
|
||||
|
||||
hostCount=0
|
||||
for testHostDir in ${allTestHostDirs}; do hostCount=$((1+hostCount)); done
|
||||
exitedCount=0
|
||||
overallStatus=""
|
||||
|
||||
while test "${exitedCount}" -lt "${hostCount}"; do
|
||||
width="$(tput cols 2>/dev/null)"
|
||||
test -n "${width}" || width=80
|
||||
|
||||
currentEpoch="$(date +%s)"
|
||||
elapsedSeconds=$((currentEpoch-startEpoch))
|
||||
|
||||
{
|
||||
nameWidth=0
|
||||
runningCount=0
|
||||
failedCount=0
|
||||
passedCount=0
|
||||
exitedCount=0
|
||||
overallStatus=""
|
||||
for testHostDir in ${allTestHostDirs}; do
|
||||
hostSpec="${testHostDir}"
|
||||
{ read -r hostSpec < "${workDir}/${testHostDir}/hostSpec"; } 2>/dev/null
|
||||
test "${#hostSpec}" -gt "${nameWidth}" && nameWidth="${#hostSpec}"
|
||||
|
||||
exec 3>>"${workDir}/${testHostDir}/active"
|
||||
flock -x -n 3 && exitedCount=$((1+exitedCount))
|
||||
exec 3<&-
|
||||
|
||||
test -e "${workDir}/${testHostDir}/ended" || runningCount=$((1+runningCount))
|
||||
if test -e "${workDir}/${testHostDir}/failed"; then
|
||||
overallStatus="FAIL"
|
||||
failedCount=$((1+failedCount))
|
||||
elif test -e "${workDir}/${testHostDir}/succeeded"; then
|
||||
test -z "${overallStatus}" && overallStatus="PASS"
|
||||
passedCount=$((1+passedCount))
|
||||
fi
|
||||
done
|
||||
test -n "${overallStatus}" || overallStatus="----"
|
||||
|
||||
printf "%sT+%04d - %s%s\n\n" "${attrUnderline}" "${elapsedSeconds}" "$(date '+%Y-%m-%d %H:%M:%S')" "${attrNone}"
|
||||
|
||||
for testHostDir in ${allTestHostDirs}; do
|
||||
hostSpec="${testHostDir}"
|
||||
{ read -r hostSpec < "${workDir}/${testHostDir}/hostSpec"; } 2>/dev/null
|
||||
|
||||
lastStatusWord="-"
|
||||
lastStatusMessage="-"
|
||||
{ read -r lastStatusWord lastStatusMessage < "${workDir}/${testHostDir}/last-status"; } 2>/dev/null
|
||||
|
||||
lastLine="-"
|
||||
test -s "${workDir}/${testHostDir}/output.log" && lastLine="$(tail -n 1 "${workDir}/${testHostDir}/output.log" 2>/dev/null | expand)"
|
||||
|
||||
testResult="----"
|
||||
test -e "${workDir}/${testHostDir}/failed" && testResult="FAIL"
|
||||
test -e "${workDir}/${testHostDir}/succeeded" && testResult="PASS"
|
||||
|
||||
remainingWidth=$((width-nameWidth-20))
|
||||
statusWidth=$((remainingWidth*2/3))
|
||||
test "${statusWidth}" -gt 40 && statusWidth=40
|
||||
lastLineWidth=$((remainingWidth-statusWidth))
|
||||
|
||||
printf " %s%${nameWidth}s%s " "${attrBold}${attrYellow}" "${hostSpec}" "${attrNone}"
|
||||
case "${testResult}" in
|
||||
"PASS") printf "%s%s%s" "${attrBold}${attrGreen}" "PASS" "${attrNone}" ;;
|
||||
"FAIL") printf "%s%s%s" "${attrBold}${attrRed}" "FAIL" "${attrNone}" ;;
|
||||
*) printf "%s" "----"
|
||||
esac
|
||||
|
||||
case "${lastStatusWord}" in
|
||||
"(begin)"|"begin") printf " (%s%s%s) " "${attrBold}${attrMagenta}" "begin" "${attrNone}" ;;
|
||||
"(end)"|"end") printf " (%s%s%s) " "${attrBold}${attrMagenta}" "end" "${attrNone}" ;;
|
||||
"(notice)"|"notice") printf " (%s%s%s) " "${attrBold}${attrCyan}" "notice" "${attrNone}" ;;
|
||||
"(ok)"|"ok") printf " (%s%s%s) " "${attrBold}${attrGreen}" "ok" "${attrNone}" ;;
|
||||
"(warning)"|"warning") printf " (%s%s%s)" "${attrBold}${attrYellow}" "warning" "${attrNone}" ;;
|
||||
"(error)"|"error") printf " (%s%s%s) " "${attrBold}${attrRed}" "error" "${attrNone}" ;;
|
||||
*) printf " %7s " ""; lastStatusMessage="${lastStatusWord} ${lastStatusMessage}" ;;
|
||||
esac
|
||||
printf " %s%-${statusWidth}.${statusWidth}s%s" "${attrWhite}" "${lastStatusMessage}" "${attrNone}"
|
||||
printf " %s%-${lastLineWidth}.${lastLineWidth}s%s" "${attrBlue}" "${lastLine}" "${attrNone}"
|
||||
printf "\n"
|
||||
done
|
||||
|
||||
printf "\n%s%s%s " "${attrBold}" "Overall status:" "${attrNone}"
|
||||
case "${overallStatus}" in
|
||||
"PASS") printf "%s%s%s" "${attrBold}${attrGreen}" "PASS" "${attrNone}" ;;
|
||||
"FAIL") printf "%s%s%s" "${attrBold}${attrRed}" "FAIL" "${attrNone}" ;;
|
||||
*) printf "%s" "----"
|
||||
esac
|
||||
|
||||
printf " %s%s%s " "${attrBold}" "Running,Passed,Failed:" "${attrNone}"
|
||||
printf "%sR%d%s" "${attrBold}${attrMagenta}" "${runningCount}" "${attrNone}"
|
||||
printf ",%sP%d%s" "${attrBold}${attrGreen}" "${passedCount}" "${attrNone}"
|
||||
printf ",%sF%d%s" "${attrBold}${attrRed}" "${failedCount}" "${attrNone}"
|
||||
printf " = %d" "${hostCount}"
|
||||
printf "\n\n"
|
||||
} > "${workDir}/latest-status.txt"
|
||||
|
||||
cat "${workDir}/latest-status.txt"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
endEpoch="$(date +%s)"
|
||||
elapsedSeconds=$((endEpoch-startEpoch))
|
||||
|
||||
printf '%s\n' 'Generating results archive'
|
||||
tar czf "${resultsArchive}" -C "${workDir}" .
|
||||
|
||||
printf '%s: %d%s\n' 'Total time taken' "${elapsedSeconds}" "s"
|
||||
printf '%s: %s\n' 'Results archive' "${resultsArchive}"
|
||||
|
||||
test "${overallStatus}" = "PASS" || exit 1
|
||||
Reference in New Issue
Block a user