aur/build.sh
nyyu fea1198402
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
chore(ci): sort folders
2025-04-09 08:39:53 +02:00

253 lines
6.3 KiB
Bash
Executable file

#!/bin/bash
set -euo pipefail
# Constants
readonly REQUIRED_ENV_VARS=(BUILD_DIR REPO_DIR GIT_USER_EMAIL GIT_USER_NAME CI_FORGE_URL CI_REPO_CLONE_URL GIT_USER GIT_TOKEN)
readonly REQUIRED_COMMANDS=(makepkg repo-add git pacman)
# Colors for logging
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
trap 'echo -e "${RED}Error on line $LINENO${NC}"' ERR
. .util.sh
log() {
local level=$1
shift
local color="${NC}"
case "${level}" in
"ERROR") color="${RED}" ;;
"WARN") color="${YELLOW}" ;;
"INFO") color="${GREEN}" ;;
esac
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] ${color}${level}${NC}: $*"
}
check_dependencies() {
local missing_cmds=()
for cmd in "${REQUIRED_COMMANDS[@]}"; do
if ! command -v "${cmd}" >/dev/null 2>&1; then
missing_cmds+=("${cmd}")
fi
done
if [[ ${#missing_cmds[@]} -gt 0 ]]; then
log "ERROR" "Missing required commands: ${missing_cmds[*]}"
exit 1
fi
}
validate_env_vars() {
local missing_vars=()
for var in "${REQUIRED_ENV_VARS[@]}"; do
if [[ -z "${!var:-}" ]]; then
missing_vars+=("$var")
fi
done
if [[ ${#missing_vars[@]} -gt 0 ]]; then
log "ERROR" "Missing required environment variables: ${missing_vars[*]}"
exit 1
fi
}
cleanup_build_dir() {
git clean -fdx
if [[ -d "${BUILD_DIR}" ]]; then
rm -rf "${BUILD_DIR:?}"/*
else
log "INFO" "Creating build directory"
mkdir -p "${BUILD_DIR}"
fi
}
build() {
local upd=${1:-false}
local name ver rel epoch
cleanup_build_dir
if grep -q 'git+' PKGBUILD && ! grep -q '#tag=' PKGBUILD; then
if ! makepkg --noprepare --nodeps --nobuild --skippgpcheck --noconfirm; then
log "ERROR" "makepkg failed during preparation"
return 1
fi
if ! makepkg --printsrcinfo >.SRCINFO; then
log "ERROR" "Failed to generate .SRCINFO"
return 1
fi
[[ "${upd}" == true ]] && update_pkg
fi
name=$(grep -m1 'pkgname' .SRCINFO | cut -d'=' -f2 | tr -d ' ')
ver=$(grep -m1 'pkgver' .SRCINFO | cut -d'=' -f2 | tr -d ' ')
rel=$(grep -m1 'pkgrel' .SRCINFO | cut -d'=' -f2 | tr -d ' ')
epoch=$(grep -m1 'epoch' .SRCINFO | cut -d'=' -f2 | tr -d ' ')
[[ -n "${epoch}" ]] && epoch=${epoch}:
if pacman -Si "${name}" 2>/dev/null | grep -v nyyu | grep -q -E '^Repository'; then
log "WARN" "Found ${name} in the Arch repo"
fi
if ! compgen -G "${REPO_DIR}/${name}-${epoch}${ver}-${rel}-*.pkg.tar.zst" >/dev/null; then
log "INFO" "Building package ${name}-${epoch}${ver}-${rel}"
if ! { makepkg --nodeps --skippgpcheck --noconfirm --sign ||
makepkg -C -s --skippgpcheck --noconfirm --sign ||
makepkg -C -s --skippgpcheck --nocheck --noconfirm --sign; }; then
log "ERROR" "All build attempts failed for ${name}"
return 1
fi
for pkg in *.pkg.tar.zst; do
if [[ -f "${pkg}" ]]; then
if ! cp "${pkg}"{,.sig} "${REPO_DIR}/"; then
log "ERROR" "Failed to copy ${pkg} to repo"
return 1
fi
if ! repo-add -R -s "${REPO_DIR}/nyyu.db.tar.zst" "${REPO_DIR}/${pkg}"; then
log "ERROR" "Failed to add ${pkg} to repo database"
return 1
fi
fi
done
if ! sudo pacman -Syu --noconfirm; then
log "WARN" "Failed to update system packages"
fi
fi
return 0
}
process_directory() {
local dir=$1
if ! pushd "${dir}" >/dev/null; then
log "ERROR" "Failed to enter directory ${dir}"
return 1
fi
if [[ -f PKGBUILD ]]; then
log "INFO" "Processing ${dir}"
if [[ -f update.sh ]]; then
chmod +x update.sh
./update.sh
fi
if ! grep -q 'pkgver()' PKGBUILD; then
update_repo_tags
fi
update_pkg
build true
fi
popd >/dev/null
}
process_directories() {
local exit_status=0
local dirs=("$@")
for dir in "${dirs[@]}"; do
if ! process_directory "$dir"; then
log "ERROR" "Failed to process directory ${dir}"
exit_status=1
fi
done
return $exit_status
}
find_and_remove_deleted_packages() {
local last_commit del=()
if git cat-file -e "${CI_PREV_COMMIT_SHA:-}" 2>/dev/null; then
last_commit=${CI_PREV_COMMIT_SHA}
else
last_commit=$(git --no-pager log --oneline | grep -v 'CI SKIP' | cut -d' ' -f1 | sed -n '5p') || {
log "ERROR" "Failed to determine last commit"
return 1
}
fi
log "INFO" "Finding removed packages from ${last_commit}"
mapfile -t del < <(
{
git --no-pager diff "${last_commit}"..HEAD aur.txt | tail -n +4 | grep -E '^-' | cut -c2-
git --no-pager diff --name-status "${last_commit}"..HEAD | grep -Po 'D\s+(\K.*)(?=/PKGBUILD)'
} | sort -u
)
if [[ ${#del[@]} -gt 0 ]]; then
for pkg in "${del[@]}"; do
log "INFO" "Removing package ${pkg}"
if ! repo-remove -s "${REPO_DIR}/nyyu.db.tar.zst" "${pkg}"; then
log "WARN" "Failed to remove ${pkg} from repo"
fi
if ! rm -vf "${REPO_DIR}/${pkg}"*; then
log "WARN" "No files found for ${pkg} in ${REPO_DIR}/"
fi
done
else
log "INFO" "No packages to remove"
fi
}
setup_git() {
git config --global user.email "${GIT_USER_EMAIL}"
git config --global user.name "${GIT_USER_NAME}"
git config --global init.defaultBranch master
git remote set-url origin "${CI_REPO_CLONE_URL}"
local forge_url="${CI_FORGE_URL#https://}"
cat > "${HOME}/.netrc" <<EOF
machine ${forge_url}
login ${GIT_USER}
password ${GIT_TOKEN}
EOF
chmod 600 "${HOME}/.netrc"
}
process_aur_packages() {
if [[ ! -f aur.txt ]]; then
log "ERROR" "aur.txt not found"
exit 1
fi
while IFS= read -r pkg; do
[[ -z "$pkg" ]] && continue
log "INFO" "Processing ${pkg}"
if ! git clone "https://aur.archlinux.org/${pkg}.git" --depth 1; then
log "ERROR" "Failed to clone repository for package ${pkg}"
continue
fi
if ! pushd "${pkg}" >/dev/null; then
log "ERROR" "Failed to enter directory for package ${pkg}"
continue
fi
if ! build false; then
log "ERROR" "Failed to build ${pkg}"
fi
popd >/dev/null
rm -rf "${pkg}"
done <aur.txt
}
main() {
check_dependencies
validate_env_vars
setup_git
mapfile -t dirs < <(find . -maxdepth 1 -type d ! -name ".*" -printf "%f\n" | sort -u)
process_directories "${dirs[@]}" || log "WARN" "Some directory processing failed"
process_aur_packages
find_and_remove_deleted_packages
}
main "$@"