252 lines
8.8 KiB
Bash
Executable File
252 lines
8.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# File: maat-builder
|
|
#
|
|
# Description: This file allows a Maat host to build source packages
|
|
# and optionally upload to the AniNIX/Foundation
|
|
#
|
|
# Package: Maat
|
|
# Copyright: WTFPL
|
|
#
|
|
# Author: DarkFeather
|
|
#
|
|
|
|
# Arch keys to look for
|
|
pkgExt=".pkg.tar.zst"
|
|
deprivuser="maat"
|
|
|
|
### Printing defaults
|
|
passCell="<td style='color:#72ff72;'>PASS</td>";
|
|
failCell="<td style='color:red;'>FAIL</td>";
|
|
warnCell="<td style='color:yellow;'>N/A</td>";
|
|
tableHead="<table style='text-align: left;'>\n<tr><th>Package</th><th>Testing Status</th><th>Build Status</th><th>Latest Build</th><th>Time and Log of Run</th></tr>";
|
|
|
|
### Add helptext.
|
|
function Usage() {
|
|
echo "Usage: $0"
|
|
echo " $0 [ -b basedir ] [ -c AUR.git.list ] [ -T ] [ -u https://base.url/ ]"
|
|
echo " $0 -h"
|
|
echo
|
|
echo 'Add -v to increase verbosity or -h for help. Add the -l LOGFILE flags to log to a file'
|
|
echo 'Add the -r REPOCMD, -C make-package-command, -p PKGBUILDName, -t test-command, and'
|
|
echo 'the -e package-extension flags for compatibility with non-ArchLinux repos.'
|
|
}
|
|
|
|
### Put the initial content in the webfile
|
|
function SeedWebFile() {
|
|
printf '<html lang="en">\n<head>\n<title>AniNIX/Maat -- Build Results</title>\n<link rel="icon" type="image/png" href="/MaatIcon.png" />\n<link rel="icon" type="image/png" href="/MaatIcon.png">\n<meta name="apple-mobile-web-app-capable" content="yes" />\n<link rel="stylesheet" type="text/css" href="https://aninix.net/assets/css/theme-aninix.css">\n<link rel="apple-touch-icon" sizes="180x180" href="/MaatIcon.png" />\n</head>\n<body>\n<h1>AniNIX/Maat -- Build Status</h1>\nWEBSTATSGOHERE\n<h2>AnINIX Packages</h2>\n<p>These are packages written by the AniNIX. Their source is in <a href="https://aninix.net/" alt=AniNIX/Foundation>AniNIX/Foundation</a>.</p>\n' > "$webfile"
|
|
printf "$tableHead" >> "$webfile"
|
|
}
|
|
|
|
### Update the webfile to close up table tags and add stats.
|
|
function UpdateWebFile() {
|
|
sed -i "s#WEBSTATSGOHERE#<p>These are the AniNIX testing results. We found $passcount passing and $failcount failing packages, with $warncount warnings. It took $runtime seconds to finish.</p>#" "$webfile"
|
|
printf '</table>\n</body>\n</html>\n' >> "$webfile"
|
|
mv "$webfile" "$webfilefinal"
|
|
}
|
|
|
|
### Build the package. Assumes a PKGBUILD is resent in the repo.
|
|
# param suffix: where to store the final package
|
|
function BuildPackage() {
|
|
suffix="$1"
|
|
[ `pgrep -afc pacman` -eq 0 ] && rm -Rf /var/lib/pacman/db.lck
|
|
nice -n 10 timeout --preserve-status 60m sudo -u "$deprivuser" /usr/sbin/makepkg -sfc --noconfirm --sign &>> "$pkgdir"/"$repodir".txt
|
|
if [ $? -ne 0 ]; then
|
|
# Build failed.
|
|
printf "$failCell""$warnCell" >> "$webfile"
|
|
else
|
|
# Build passed.
|
|
printf "$passCell""<td>" >> "$webfile"
|
|
# List passing versions
|
|
for pkg in `find . -type f | grep -E "${pkgExt}""\$"`; do
|
|
printf "<a href=\"/$suffix/$pkg\">$pkg</a><br/>" >> "$webfile"
|
|
pkgname="$(basename "$pkg" | cut -f 1 -d '.' | sed 's/-[[:digit:]]\+$//')"
|
|
# Remove old copies
|
|
find "${pkgdir}/${suffix}/" -name "${pkgname}-[0-9]*" -exec rm {} \;
|
|
mv "$pkg" "$pkgdir"/"$suffix";
|
|
mv "$pkg"".sig" "$pkgdir"/"$suffix";
|
|
done
|
|
printf "</td>" >> "$webfile"
|
|
fi
|
|
}
|
|
|
|
### Build the repo passed as argument
|
|
# param repo: the repo to build.
|
|
# param suffix: where to store the final package
|
|
function BuildRepo() {
|
|
repo="$1"
|
|
suffix="$2"
|
|
cd "$srcdir"
|
|
if [ -z "$repo" ]; then continue; fi
|
|
repodir="$(basename "$repo" | sed 's/\.git$//')"
|
|
#Set up the checkout
|
|
if [ ! -d "$repodir" ]; then
|
|
git clone "$repo"
|
|
fi
|
|
cd "$repodir"
|
|
git clean -fdX
|
|
output="$(git pull 2>&1)"
|
|
if [ -n "$incremental" ] && [ $( echo "$output" | grep -c 'Already up to date.' ) -eq 1 ]; then
|
|
return;
|
|
fi
|
|
|
|
chown -R "$deprivuser": .
|
|
echo "$output" > "$pkgdir"/"$repodir".txt
|
|
# Find the PKGBuilds in the repo
|
|
for pkgbuild in `find . -type f -name PKGBUILD`; do
|
|
cd "$(dirname "$pkgbuild")"
|
|
# Tell the status file about it.
|
|
printf '<tr style="border: 1px solid #FFF;"><td>'"<a href='$(echo "$repo" | sed 's#aur.archlinux.org#aur.archlinux.org/packages#' | sed 's/.git//')'>$repodir</a> -- $pkgbuild"'</td>' >> "$webfile"
|
|
if [ -f Makefile ] && [ `grep -E -c '^test:' Makefile` -ge 1 ]; then
|
|
# Have to try to install dependencies first
|
|
for dep in $(grep makedepends PKGBUILD | cut -f 2 -d '(' | cut -f 1 -d ')' | sed "s/'//g"); do
|
|
pacman -S "$dep" --noconfirm --needed
|
|
done
|
|
# Check test status.
|
|
timeout --preserve-status "$timeout" sudo -u "$deprivuser" /bin/bash -l -c "cd $PWD; make test" &>> "$pkgdir"/"$repodir".txt
|
|
if [ $? -ne 0 ]; then
|
|
# Testing failed.
|
|
printf "$failCell""$warnCell""$warnCell" >> "$webfile"
|
|
else
|
|
# Testing passed.
|
|
printf "$passCell" >> "$webfile"
|
|
BuildPackage "$suffix"
|
|
fi
|
|
else
|
|
# Can't test -- usually from non-AniNIX repos.
|
|
printf "$warnCell" >> "$webfile"
|
|
BuildPackage "$suffix"
|
|
fi
|
|
# Timestamp
|
|
printf "<td><a href='/$repodir.txt'>$(date +%F-%R)</a></td></tr>\n" >> "$webfile"
|
|
cd "$cwd"
|
|
if [ ! -z "$testing" ]; then break; fi
|
|
done
|
|
cd "$cwd"
|
|
}
|
|
|
|
### Update the local repo
|
|
function UpdateLocalRepo() {
|
|
set -x
|
|
cd "$pkgdir"
|
|
chown -R "$deprivuser": .
|
|
rm -Rf AniNIX.[db,files]*
|
|
sudo -u "$deprivuser" repo-add --sign ./AniNIX.db.tar.zst `ls -1 *"${pkgExt}"`
|
|
cd aur/
|
|
rm -Rf aur.[db,files]*
|
|
sudo -u "$deprivuser" repo-add --sign ./aur.db.tar.zst `ls -1 *"${pkgExt}"`
|
|
set +x
|
|
}
|
|
|
|
### Clean source tracking
|
|
function CleanSrcTracking() {
|
|
searchbase="${homedir}/src"
|
|
for path in `find "$searchbase" -maxdepth 1 -mindepth 1 -type d`; do
|
|
cd "$path"
|
|
giturl="$(git config remote.origin.url)"
|
|
if ! grep "$giturl" "$aurconf"; then
|
|
cd "$searchbase"
|
|
rm -Rf "$path"
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
# Clear variables
|
|
aurconf='/usr/local/etc/Maat/aur.list'
|
|
baseurl='https://aninix.net/AniNIX'
|
|
homedir="/srv/maat/"
|
|
unset incremental
|
|
unset skipPatching
|
|
unset testing
|
|
timeout="90s"
|
|
|
|
# Stat tracking
|
|
starttime=`date +%s`
|
|
|
|
function usage() {
|
|
### Show helptext
|
|
# param retcode: what to exit
|
|
retcode="$1"
|
|
cat <<EOM
|
|
Usage: $0
|
|
$0 -T # Extended testing
|
|
$0 -b homedir -c aurconf -u user -t timeout
|
|
Add -s to skip patching or -v for verbosity.
|
|
EOM
|
|
exit $retcode
|
|
}
|
|
|
|
|
|
# Parse arguments
|
|
while getopts 'b:c:hil:st:Tu:v' OPTION; do
|
|
case "${OPTION}" in
|
|
b) homedir="${OPTARG}" ;;
|
|
c) aurconf="${OPTARG}" ;;
|
|
h) usage; exit 0 ;;
|
|
i) incremental=1 ;;
|
|
l) cmdstring="$0"; for arg in $@; do if [ "$arg" != "-l" ] && [ "$arg" != "${OPTARG}" ]; then cmdstring="$cmdstring \"${arg}\""; fi; done; exec /bin/bash -c "$cmdstring | tee -a \"${OPTARG}\""; ;;
|
|
s) skipPatching=1 ;;
|
|
t) timeout="${OPTARG}" ;;
|
|
T) export MAATTESTINGVAR=1; exec $0 -l ./testing.log -u "$deprivuser" -v -s -c <(echo https://aur.archlinux.org/ascii-invaders.git) -b . ;;
|
|
u) deprivuser="${OPTARG}" ;;
|
|
v) set -x ;;
|
|
*) echo "Internal GitOps CI/CD Pipeline"; usage 1 ;;
|
|
esac
|
|
done
|
|
|
|
# Ensure we are up to date -- otherwise, building is not a good plan.
|
|
if [ -x `which pacman` ] && [ -z "$skipPatching" ]; then
|
|
pacman -Sc --noconfirm
|
|
pacman -Syu --noconfirm
|
|
if [ $? -ne 0 ]; then
|
|
echo "Self patching failed -- please investigate!" 1>&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Ensure work directories live
|
|
if [ $( echo "$homedir" | grep -E -c '^/') -ne 1 ]; then
|
|
homedir="${PWD}/${homedir}"
|
|
fi
|
|
|
|
# Setup
|
|
srcdir="${homedir}/src" && mkdir -p "${srcdir}"
|
|
pkgdir="${homedir}/pkg" && mkdir -p "${pkgdir}"
|
|
mkdir -p "${pkgdir}"/aur
|
|
webdir="$pkgdir"
|
|
webfilefinal="$webdir"/index.html
|
|
webfile="$webdir"/index.html.tmp
|
|
cwd="$(pwd)"
|
|
SeedWebFile
|
|
|
|
# Build AniNIX Repo
|
|
if [ -n "$MAATTESTINGVAR" ]; then
|
|
BuildRepo "$baseurl"/HelloWorld
|
|
else
|
|
CleanSrcTracking
|
|
for AniNIXrepo in `curl -s "$baseurl" | grep 'class="text primary name"' | cut -f 4 -d \" | sed "s#^#https://$(echo "$baseurl" | cut -f 3 -d /)#" | sed 's/$/.git/'`; do
|
|
BuildRepo "$AniNIXrepo" '.'
|
|
done
|
|
fi
|
|
printf '</table>\n<h2>AUR Packages</h3>\n<p>These are packages made by other ArchLinux users and uploaded to the <a href="https://aur.archlinux.org/" alt="ArchLinux AUR">AUR</a>.</p>\n' >> "$webfile"
|
|
printf "$tableHead" >> "$webfile"
|
|
|
|
# Build AUR
|
|
for repo in `cat "$aurconf"`; do
|
|
BuildRepo "$repo" aur;
|
|
if [ ! -z "$MAATTESTINGVAR" ]; then break; fi
|
|
done
|
|
|
|
UpdateLocalRepo
|
|
|
|
runtime=$(( `date +%s` - $starttime ))
|
|
|
|
# Update stats
|
|
failcount=$(grep -c "$failCell" "$webfile")
|
|
warncount=$(grep -c "$warnCell" "$webfile")
|
|
passcount=$( grep -v "$failCell" "$webfile" | grep -c "$passCell" )
|
|
UpdateWebFile
|
|
|
|
# Exit
|