2019-02-18 07:56:39 -06:00
#!/bin/bash
# File: maat-builder
#
# Description: This file allows a Maat host to build source packages
2020-02-07 16:12:39 -06:00
# and optionally upload to the AniNIX/Foundation
2019-02-18 07:56:39 -06:00
#
2020-02-07 16:12:39 -06:00
# Package: Maat
2019-02-18 07:56:39 -06:00
# Copyright: WTFPL
#
2020-02-07 16:12:39 -06:00
# Author: DarkFeather
2023-02-22 17:56:30 -06:00
#
# Arch keys to look for
pkgExt = ".pkg.tar.zst"
deprivuser = "maat"
2019-02-18 07:56:39 -06:00
### Printing defaults
2024-04-25 13:42:46 -05:00
passCell = "<td style='color:#72ff72;'>PASS</td>" ;
2019-04-08 05:05:08 -05:00
failCell = "<td style='color:red;'>FAIL</td>" ;
warnCell = "<td style='color:yellow;'>N/A</td>" ;
2019-07-25 13:01:53 -05:00
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>" ;
2019-02-18 07:56:39 -06:00
### Add helptext.
function Usage() {
echo "Usage: $0 "
2019-07-25 13:01:53 -05:00
echo " $0 [ -b basedir ] [ -c AUR.git.list ] [ -T ] [ -u https://base.url/ ]"
2019-02-18 07:56:39 -06:00
echo " $0 -h"
echo
echo 'Add -v to increase verbosity or -h for help. Add the -l LOGFILE flags to log to a file'
2019-07-25 13:01:53 -05:00
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.'
2019-02-18 07:56:39 -06:00
}
### Put the initial content in the webfile
function SeedWebFile() {
2024-04-25 13:42:46 -05:00
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 "
2019-07-25 13:01:53 -05:00
printf " $tableHead " >> " $webfile "
2019-02-18 07:56:39 -06:00
}
2023-02-22 17:56:30 -06:00
### Update the webfile to close up table tags and add stats.
2019-02-18 07:56:39 -06:00
function UpdateWebFile() {
2019-07-25 13:01:53 -05:00
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 "
2019-02-18 07:56:39 -06:00
}
### Build the package. Assumes a PKGBUILD is resent in the repo.
2019-07-25 13:01:53 -05:00
# param suffix: where to store the final package
2023-02-22 17:56:30 -06:00
function BuildPackage() {
2019-07-25 13:01:53 -05:00
suffix = " $1 "
[ ` pgrep -afc pacman` -eq 0 ] && rm -Rf /var/lib/pacman/db.lck
2023-02-22 17:56:30 -06:00
nice -n 10 timeout --preserve-status 60m sudo -u " $deprivuser " /usr/sbin/makepkg -sfc --noconfirm --sign & >> " $pkgdir " /" $repodir " .txt
2019-02-18 07:56:39 -06:00
if [ $? -ne 0 ] ; then
# Build failed.
2023-02-22 17:56:30 -06:00
printf " $failCell "" $warnCell " >> " $webfile "
2019-02-18 07:56:39 -06:00
else
# Build passed.
printf " $passCell ""<td>" >> " $webfile "
# List passing versions
2023-02-22 17:56:30 -06:00
for pkg in ` find . -type f | grep -E " ${ pkgExt } ""\$" ` ; do
2020-02-07 16:12:39 -06:00
printf "<a href=\"/ $suffix / $pkg \"> $pkg </a><br/>" >> " $webfile "
2023-02-22 17:56:30 -06:00
pkgname = " $( basename " $pkg " | cut -f 1 -d '.' | sed 's/-[[:digit:]]\+$//' ) "
2024-04-07 23:39:27 -05:00
# Remove old copies
2023-02-22 17:56:30 -06:00
find " ${ pkgdir } / ${ suffix } /" -name " ${ pkgname } -[0-9]*" -exec rm {} \;
mv " $pkg " " $pkgdir " /" $suffix " ;
mv " $pkg "".sig" " $pkgdir " /" $suffix " ;
2019-07-25 13:01:53 -05:00
done
2020-02-07 16:12:39 -06:00
printf "</td>" >> " $webfile "
2019-02-18 07:56:39 -06:00
fi
}
### Build the repo passed as argument
# param repo: the repo to build.
2019-07-25 13:01:53 -05:00
# param suffix: where to store the final package
2019-02-18 07:56:39 -06:00
function BuildRepo() {
repo = " $1 "
2019-07-25 13:01:53 -05:00
suffix = " $2 "
2019-02-18 07:56:39 -06:00
cd " $srcdir "
if [ -z " $repo " ] ; then continue ; fi
2019-04-08 05:05:08 -05:00
repodir = " $( basename " $repo " | sed 's/\.git$//' ) "
2019-02-18 07:56:39 -06:00
#Set up the checkout
if [ ! -d " $repodir " ] ; then
git clone " $repo "
fi
2023-02-22 17:56:30 -06:00
cd " $repodir "
2023-10-08 17:03:57 -05:00
git clean -fdX
2019-04-08 05:05:08 -05:00
output = " $( git pull 2>& 1) "
2023-02-22 17:56:30 -06:00
if [ -n " $incremental " ] && [ $( echo " $output " | grep -c 'Already up to date.' ) -eq 1 ] ; then
return ;
fi
chown -R " $deprivuser " : .
2019-07-25 13:01:53 -05:00
echo " $output " > " $pkgdir " /" $repodir " .txt
2019-02-18 07:56:39 -06:00
# Find the PKGBuilds in the repo
for pkgbuild in ` find . -type f -name PKGBUILD` ; do
cd " $( dirname " $pkgbuild " ) "
# Tell the status file about it.
2024-04-07 23:39:27 -05:00
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 "
2023-02-22 17:56:30 -06:00
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
2024-04-07 23:39:27 -05:00
pacman -S " $dep " --noconfirm --needed
2023-02-22 17:56:30 -06:00
done
2019-02-18 07:56:39 -06:00
# Check test status.
2023-02-22 17:56:30 -06:00
timeout --preserve-status " $timeout " sudo -u " $deprivuser " /bin/bash -l -c "cd $PWD ; make test" & >> " $pkgdir " /" $repodir " .txt
2019-02-18 07:56:39 -06:00
if [ $? -ne 0 ] ; then
# Testing failed.
printf " $failCell "" $warnCell "" $warnCell " >> " $webfile "
else
# Testing passed.
printf " $passCell " >> " $webfile "
2019-07-25 13:01:53 -05:00
BuildPackage " $suffix "
2019-02-18 07:56:39 -06:00
fi
2023-02-22 17:56:30 -06:00
else
2019-02-18 07:56:39 -06:00
# Can't test -- usually from non-AniNIX repos.
printf " $warnCell " >> " $webfile "
2019-07-25 13:01:53 -05:00
BuildPackage " $suffix "
2019-02-18 07:56:39 -06:00
fi
# Timestamp
2020-02-07 16:12:39 -06:00
printf "<td><a href='/ $repodir .txt'> $( date +%F-%R) </a></td></tr>\n" >> " $webfile "
2019-02-18 07:56:39 -06:00
cd " $cwd "
if [ ! -z " $testing " ] ; then break; fi
done
2023-02-22 17:56:30 -06:00
cd " $cwd "
2019-02-18 07:56:39 -06:00
}
2023-02-22 17:56:30 -06:00
### Update the local repo
function UpdateLocalRepo() {
2019-07-25 13:01:53 -05:00
set -x
2023-02-22 17:56:30 -06:00
cd " $pkgdir "
chown -R " $deprivuser " : .
rm -Rf AniNIX.[ db,files] *
sudo -u " $deprivuser " repo-add --sign ./AniNIX.db.tar.zst ` ls -1 *" ${ pkgExt } " `
2019-07-25 13:01:53 -05:00
cd aur/
rm -Rf aur.[ db,files] *
2023-02-22 17:56:30 -06:00
sudo -u " $deprivuser " repo-add --sign ./aur.db.tar.zst ` ls -1 *" ${ pkgExt } " `
2019-07-25 13:01:53 -05:00
set +x
2019-02-18 07:56:39 -06:00
}
2024-04-04 17:04:19 -05:00
### 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
}
2019-07-25 13:01:53 -05:00
# Clear variables
2019-02-18 07:56:39 -06:00
aurconf = '/usr/local/etc/Maat/aur.list'
2023-02-22 17:56:30 -06:00
baseurl = 'https://aninix.net/AniNIX'
2019-07-25 13:01:53 -05:00
homedir = "/srv/maat/"
2019-04-08 05:05:08 -05:00
unset incremental
2019-07-25 13:01:53 -05:00
unset skipPatching
unset testing
timeout = "90s"
2019-02-18 07:56:39 -06:00
# Stat tracking
starttime = ` date +%s`
2023-10-03 13:01:50 -05:00
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
}
2019-02-18 07:56:39 -06:00
# Parse arguments
2023-02-22 17:56:30 -06:00
while getopts 'b:c:hil:st:Tu:v' OPTION; do
2019-02-18 07:56:39 -06:00
case " ${ OPTION } " in
b) homedir = " ${ OPTARG } " ;;
c) aurconf = " ${ OPTARG } " ;;
2023-10-03 13:01:50 -05:00
h) usage; exit 0 ;;
2019-04-08 05:05:08 -05:00
i) incremental = 1 ;;
2019-07-25 13:01:53 -05:00
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 } " ;;
2023-02-22 17:56:30 -06:00
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 } " ;;
2019-02-18 07:56:39 -06:00
v) set -x ;;
2023-10-03 13:01:50 -05:00
*) echo "Internal GitOps CI/CD Pipeline" ; usage 1 ;;
2019-02-18 07:56:39 -06:00
esac
done
2019-07-25 13:01:53 -05:00
# Ensure we are up to date -- otherwise, building is not a good plan.
2023-02-22 17:56:30 -06:00
if [ -x ` which pacman` ] && [ -z " $skipPatching " ] ; then
pacman -Sc --noconfirm
pacman -Syu --noconfirm
2019-07-25 13:01:53 -05:00
if [ $? -ne 0 ] ; then
echo "Self patching failed -- please investigate!" 1>& 2
exit 1
fi
fi
2019-02-18 07:56:39 -06:00
# Ensure work directories live
2023-02-22 17:56:30 -06:00
if [ $( echo " $homedir " | grep -E -c '^/' ) -ne 1 ] ; then
2019-02-18 07:56:39 -06:00
homedir = " ${ PWD } / ${ homedir } "
fi
2019-07-25 13:01:53 -05:00
# Setup
2019-02-18 07:56:39 -06:00
srcdir = " ${ homedir } /src" && mkdir -p " ${ srcdir } "
pkgdir = " ${ homedir } /pkg" && mkdir -p " ${ pkgdir } "
2019-07-25 13:01:53 -05:00
mkdir -p " ${ pkgdir } " /aur
2019-04-08 05:05:08 -05:00
webdir = " $pkgdir "
2019-07-25 13:01:53 -05:00
webfilefinal = " $webdir " /index.html
webfile = " $webdir " /index.html.tmp
2019-02-18 07:56:39 -06:00
cwd = " $( pwd ) "
SeedWebFile
2019-07-25 13:01:53 -05:00
# Build AniNIX Repo
if [ -n " $MAATTESTINGVAR " ] ; then
BuildRepo " $baseurl " /HelloWorld
else
2024-04-04 17:04:19 -05:00
CleanSrcTracking
2026-07-15 11:49:08 -05:00
for AniNIXrepo in ` curl -s " $baseurl " | grep 'class="tw-text-primary name"' | cut -f 4 -d \" | sed "s#^#https:// $( echo " $baseurl " | cut -f 3 -d /) #" | sed 's/$/.git/' ` ; do
2019-07-25 13:01:53 -05:00
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
2019-02-18 07:56:39 -06:00
for repo in ` cat " $aurconf " ` ; do
2023-02-22 17:56:30 -06:00
BuildRepo " $repo " aur;
2019-07-25 13:01:53 -05:00
if [ ! -z " $MAATTESTINGVAR " ] ; then break; fi
2019-02-18 07:56:39 -06:00
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