Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to create a makeshift Arch Linux repository in GitHub releases #12

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM archlinux:latest
FROM archlinux:base-devel

COPY entrypoint.sh /entrypoint.sh

Expand Down
38 changes: 37 additions & 1 deletion action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ inputs:
description: "Relative path to directory containing the PKGBUILD file."
required: false
default: "."
pacmanConf:
description: "Relative path to alternative configuration file for pacman."
required: false
default: "/etc/pacman.conf"
aurDeps:
description: "Support AUR dependencies if nonempty."
required: false
Expand All @@ -29,11 +33,43 @@ inputs:
description: "Additional arguments to pass to makepkg."
required: false
default: ""
makepkgConf:
description: "Relative path to alternative configuration file for makepkg."
required: false
default: "/etc/makepkg.conf"
multilib:
description: "Install 'multilib-devel' to build lib32 packages."
required: false
default: false
repoReleaseTag:
description: "Tag to use as repository name."
required: false
default: ""
outputs:
pkgfile0:
description: "Filename of the first generated package archive. Usually only one."
pkgfile1:
description: "Filename of the 2nd generated package archive, etc."
description: "Filename of the 2nd generated package archive."
pkgfile2:
description: "Filename of the 3rd generated package archive."
pkgfile3:
description: "Filename of the 4th generated package archive. etc."
oldfile0:
description: "Filename of the first removed package archive. Usually only one."
oldfile1:
description: "Filename of the 2nd removed package archive."
oldfile2:
description: "Filename of the 3rd removed package archive."
oldfile3:
description: "Filename of the 4th removed package archive. etc."
repofile0:
description: "<repoReleaseTag>.db"
repofile1:
description: "<repoReleaseTag>.db.tar.gz"
repofile2:
description: "<repoReleaseTag>.files"
repofile3:
description: "<repoReleaseTag>.files.tar.gz"
runs:
using: 'docker'
image: 'Dockerfile'
109 changes: 97 additions & 12 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,31 @@ cat << EOM >> /etc/pacman.conf
Include = /etc/pacman.d/mirrorlist
EOM

pacman -Syu --noconfirm --needed base-devel
# Add alerque repository for paru
cat << EOM >> /etc/pacman.conf
[alerque]
SigLevel = Optional TrustAll
Server = https://arch.alerque.com/\$arch
EOM
pacman-key --recv-keys 63CC496475267693

if [ -n "${INPUT_PACMANCONF:-}" ]; then
echo "Using ${INPUT_PACMANCONF:-} as pacman.conf"
cp "${INPUT_PACMANCONF:-}" /etc/pacman.conf
fi

if [ -n "${INPUT_MAKEPKGCONF:-}" ]; then
echo "Using ${INPUT_MAKEPKGCONF:-} as makepkg.conf"
cp "${INPUT_MAKEPKGCONF:-}" /etc/makepkg.conf
fi

pacman -Syu --noconfirm --needed base base-devel
pacman -Syu --noconfirm --needed ccache
#pacman -Syu --noconfirm --needed ccache-ext

if [ "${INPUT_MULTILIB:-false}" == true ]; then
pacman -Syu --noconfirm --needed multilib-devel
fi

# Makepkg does not allow running as root
# Create a new user `builder`
Expand All @@ -26,6 +50,27 @@ chmod -R a+rw .
BASEDIR="$PWD"
cd "${INPUT_PKGDIR:-.}"

function download_database () {
# Download the repository files if a repository tag has been specified
# This is put here to fail early in case they weren't downloaded
REPOFILES=("${INPUT_REPORELEASETAG:-}".{db{,.tar.gz},files{,.tar.gz}})
for REPOFILE in "${REPOFILES[@]}"; do
sudo -u builder curl \
--retry 5 --retry-delay 30 --retry-all-errors \
--location --fail \
-o "$REPOFILE" "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY"/releases/download/"${INPUT_REPORELEASETAG:-}"/"$REPOFILE"
done
# Delete the `<repo_name>.db` and `repo_name.files` symlinks
rm "${INPUT_REPORELEASETAG:-}".{db,files} || true
}

if [ -n "${INPUT_REPORELEASETAG:-}" ]; then
# Download database files to test for availability
download_database
# Delete them because they will be downloaded again
rm "${INPUT_REPORELEASETAG:-}".{db,files}.tar.gz
fi

# Assume that if .SRCINFO is missing then it is generated elsewhere.
# AUR checks that .SRCINFO exists so a missing file can't go unnoticed.
if [ -f .SRCINFO ] && ! sudo -u builder makepkg --printsrcinfo | diff - .SRCINFO; then
Expand All @@ -35,18 +80,13 @@ fi

# Optionally install dependencies from AUR
if [ -n "${INPUT_AURDEPS:-}" ]; then
# First install yay
pacman -S --noconfirm --needed git
git clone https://aur.archlinux.org/yay-bin.git /tmp/yay
pushd /tmp/yay
chmod -R a+rw .
sudo -H -u builder makepkg --syncdeps --install --noconfirm
popd
# First install paru
pacman -Syu --noconfirm paru

# Extract dependencies from .SRCINFO (depends or depends_x86_64) and install
mapfile -t PKGDEPS < \
<(sed -n -e 's/^[[:space:]]*\(make\)\?depends\(_x86_64\)\? = \([[:alnum:][:punct:]]*\)[[:space:]]*$/\3/p' .SRCINFO)
sudo -H -u builder yay --sync --noconfirm "${PKGDEPS[@]}"
sudo -H -u builder paru --sync --noconfirm "${PKGDEPS[@]}"
fi

# Make the builder user the owner of these files
Expand All @@ -58,26 +98,71 @@ chown -R builder .
# Build packages
# INPUT_MAKEPKGARGS is intentionally unquoted to allow arg splitting
# shellcheck disable=SC2086
sudo -H -u builder makepkg --syncdeps --noconfirm ${INPUT_MAKEPKGARGS:-}
sudo -H -u builder CCACHE_DIR="$BASEDIR/.ccache" makepkg --syncdeps --noconfirm ${INPUT_MAKEPKGARGS:-}

# Get array of packages to be built
mapfile -t PKGFILES < <( sudo -u builder makepkg --packagelist )
# shellcheck disable=SC2086
mapfile -t PKGFILES < <( sudo -u builder makepkg --packagelist ${INPUT_MAKEPKGARGS:-})
echo "Package(s): ${PKGFILES[*]}"

if [ -n "${INPUT_REPORELEASETAG:-}" ]; then
# Download database files again in case another action updated them in the meantime
download_database
# Create package file list for the old database
zcat "${INPUT_REPORELEASETAG:-}".db.tar.gz | strings | grep '.pkg.tar.' | sort > old_db.packages
fi

# Report built package archives
i=0
for PKGFILE in "${PKGFILES[@]}"; do
# Replace colon (:) in files name because releases don't like it
# It seems to not mess with pacman so it doesn't need to be guarded
srcdir="$(dirname "$PKGFILE")"
srcfile="$(basename "$PKGFILE")"
if [[ "$srcfile" == *:* ]]; then
dest="$srcdir/${srcfile//:/.}"
mv "$PKGFILE" "$dest"
PKGFILE="$dest"
fi
# makepkg reports absolute paths, must be relative for use by other actions
RELPKGFILE="$(realpath --relative-base="$BASEDIR" "$PKGFILE")"
# Caller arguments to makepkg may mean the pacakge is not built
if [ -f "$PKGFILE" ]; then
echo "::set-output name=pkgfile$i::$RELPKGFILE"
echo "pkgfile$i=$RELPKGFILE" >> $GITHUB_OUTPUT
# Optionally add the packages to a makeshift repository in GitHub releases
if [ -n "${INPUT_REPORELEASETAG:-}" ]; then
sudo -u builder repo-add "${INPUT_REPORELEASETAG:-}".db.tar.gz "$(basename "$PKGFILE")"
else
echo "Skipping repository update for $RELPKGFILE"
fi
else
echo "Archive $RELPKGFILE not built"
fi
(( ++i ))
done

if [ -n "${INPUT_REPORELEASETAG:-}" ]; then
# Delete the `<repo_name>.db` and `repo_name.files` symlinks
rm "${INPUT_REPORELEASETAG:-}".{db,files}
# Copy repo archives to their suffix-less symlinks because symlinks are not uploaded to GitHub releases
cp "${INPUT_REPORELEASETAG:-}".db{.tar.gz,}
cp "${INPUT_REPORELEASETAG:-}".files{.tar.gz,}
REPOFILES=("${INPUT_REPORELEASETAG:-}".{db{,.tar.gz},files{,.tar.gz}})
j=0
for REPOFILE in "${REPOFILES[@]}"; do
RELREPOFILE="$(realpath --relative-base="$BASEDIR" "$(realpath -s "$REPOFILE")")"
echo "repofile$j=$RELREPOFILE" >> $GITHUB_OUTPUT
(( ++j ))
done
# List package files removed from the database
zcat "${INPUT_REPORELEASETAG:-}".db.tar.gz | strings | grep '.pkg.tar.' | sort > new_db.packages
k=0
for OLDFILE in $(diff {old,new}_db.packages | grep -E "^<" | cut -c3-);do
echo "oldfile$k=$OLDFILE" >> $GITHUB_OUTPUT
(( ++k ))
done
fi

function prepend () {
# Prepend the argument to each input line
while read -r line; do
Expand Down