7 Commits

10 changed files with 156 additions and 108 deletions
+4 -3
View File
@@ -19,6 +19,7 @@ AUR_MAINTAINER_EMAIL=your@email.com
# How often to poll the AUR for updates, in seconds (default: 3600 = 1 hour) # How often to poll the AUR for updates, in seconds (default: 3600 = 1 hour)
POLL_INTERVAL_SECONDS=3600 POLL_INTERVAL_SECONDS=3600
# Number of CPU cores to use for compilation (default: all available cores) # Number of CPU cores to use for compilation (default: 4)
# Reduce this if you want to leave headroom for other processes on the server # This controls both the make -jN parallelism inside the build and the CPU
# NPROC=4 # cap enforced by Docker on the container. Set it once, it applies everywhere
NPROC=4
+16 -10
View File
@@ -1,20 +1,26 @@
# Secrets # Secrets
.env .env
# Build artifacts # Build state — artifacts are large binaries, last_version is runtime state
state/artifacts/ state/
state/build.log
state/cron.log
# AUR SSH key (if stored locally) # AUR clones — managed at runtime by the container, not part of the repo
webkit2gtk/
webkit2gtk-bin/
# makepkg build leftovers (if they end up in the workspace)
*.pkg.tar.zst
*.pkg.tar.zst.sig
src/
pkg/
# AUR SSH keys if stored locally
*.pem *.pem
*.key *.key
id_rsa id_rsa
id_ed25519 id_ed25519
# Docker # Editor
.docker/
# Misc
*.tmp
*.swp *.swp
*.tmp
.DS_Store
-66
View File
@@ -10,72 +10,6 @@ RUN pacman -Syu --noconfirm && \
jq \ jq \
openssh \ openssh \
github-cli \ github-cli \
# webkit2gtk makedepends
clang \
cmake \
gi-docgen \
glib2-devel \
gobject-introspection \
gperf \
gst-plugins-bad \
lld \
ninja \
python \
ruby \
ruby-stdlib \
systemd \
unifdef \
wayland-protocols \
# webkit2gtk runtime depends
at-spi2-core \
atk \
bubblewrap \
cairo \
enchant \
expat \
fontconfig \
freetype2 \
gdk-pixbuf2 \
glib2 \
glibc \
gst-plugins-bad-libs \
gst-plugins-base-libs \
gstreamer \
gtk3 \
harfbuzz \
harfbuzz-icu \
hyphen \
icu \
lcms2 \
libatomic \
libavif \
libdrm \
libegl \
libepoxy \
libgcrypt \
libgl \
libjpeg-turbo \
libjxl \
libmanette \
libpng \
libseccomp \
libsecret \
libsoup \
libsystemd \
libtasn1 \
libwebp \
libx11 \
libxml2 \
libxslt \
mesa \
openjpeg2 \
pango \
sqlite \
ttf-dejavu \
wayland \
woff2 \
xdg-dbus-proxy \
zlib \
&& pacman -Scc --noconfirm && pacman -Scc --noconfirm
# Non-root build user (makepkg refuses to run as root) # Non-root build user (makepkg refuses to run as root)
+80
View File
@@ -0,0 +1,80 @@
# webkit2gtk-automator
Automated builder and AUR publisher for [webkit2gtk](https://aur.archlinux.org/packages/webkit2gtk), running on a self-hosted server.
Every hour the container polls the AUR for a new webkit2gtk version. When an update is detected, it builds the package from source inside an isolated Arch Linux container and publishes the resulting binary as a [webkit2gtk-bin](https://aur.archlinux.org/packages/webkit2gtk-bin) AUR package, with the prebuilt artifact hosted on [GitHub Releases](https://github.com/Brodino96/webkit2gtk-automator/releases).
## How it works
```
docker compose up -d
└── container starts
every hour:
├── query AUR RPC API for webkit2gtk version
├── if unchanged → sleep
└── if newer →
git pull webkit2gtk PKGBUILD
makepkg (all available cores)
upload .pkg.tar.zst to GitHub Releases
update webkit2gtk-bin PKGBUILD + .SRCINFO
git push to AUR
```
## Setup
**1) Clone the repository**
```bash
git clone https://github.com/Brodino96/webkit2gtk-automator.git
cd webkit2gtk-automator
```
**2) Configure the environment**
```bash
cp .env.example .env
```
Edit `.env` and fill in:
| Variable | Description |
|---------------------------|-----------------------------------------------------------------------------------|
| `GITHUB_TOKEN` | Personal access token with **Contents: read/write** on this repo |
| `GITHUB_REPO` | `Brodino96/webkit2gtk-automator` |
| `AUR_SSH_KEY_PATH` | Absolute path to the SSH private key registered on your AUR account |
| `AUR_PACKAGE_NAME` | `webkit2gtk-bin` |
| `AUR_MAINTAINER_NAME` | Your name (written into the published PKGBUILD) |
| `AUR_MAINTAINER_EMAIL` | Your email (written into the published PKGBUILD) |
| `POLL_INTERVAL_SECONDS` | How often to check for updates, in seconds (default: `3600`) |
| `NPROC` | CPU cores for compilation, also caps the container's CPU quota (default: `4`) |
**3) Start the daemon**
```bash
docker compose up -d
```
**4) Optional - Watch the logs**
```bash
docker compose logs -f
```
## Useful commands
```bash
# Stop the daemon
docker compose down
# Rebuild the image after a Dockerfile change
docker compose up -d --build
# Force a rebuild on next poll (reset the tracked version)
rm state/last_version
docker compose restart
```
## Notes
- The build takes 13 hours depending on server hardware
- If an artifact for the current version already exists in `state/artifacts/`, the build step is skipped and the existing file is published directly (useful for testing)
- All logs go to stdout and are accessible via `docker compose logs`
- The `state/` directory is created at runtime and is not tracked by git
+7 -5
View File
@@ -8,14 +8,16 @@ services:
restart: unless-stopped restart: unless-stopped
env_file: env_file:
- .env - .env
# By default Docker exposes all host CPUs to the container. # NPROC in .env controls both the number of compiler jobs (make -jN) and
# You can cap it here or set NPROC in .env to limit parallelism at the build level. # the CPU cap enforced by the kernel. Set it once, it applies everywhere
# cpus: '4' cpus: '${NPROC:-4}'
mem_limit: 12g
memswap_limit: 12g
volumes: volumes:
# Entire project mounted so the container can read/write state, artifacts, # Entire project mounted so the container can read/write state, artifacts,
# and the webkit2gtk / webkit2gtk-bin git repos. # and the webkit2gtk / webkit2gtk-bin git repos
- .:/workspace - .:/workspace
# AUR SSH private key (path set in .env via AUR_SSH_KEY_PATH) # AUR SSH private key (path set in .env via AUR_SSH_KEY_PATH)
- ${AUR_SSH_KEY_PATH}:/run/secrets/aur_id_rsa:ro - ${AUR_SSH_KEY_PATH}:/run/secrets/aur_id_rsa:ro
# No ports needed this is a pure background worker. # No ports needed this is a pure background worker
# Logs are available via: docker compose logs -f # Logs are available via: docker compose logs -f
+14
View File
@@ -22,6 +22,20 @@ fi
mkdir -p "${ARTIFACTS_DIR}" mkdir -p "${ARTIFACTS_DIR}"
# Skip rebuild if artifacts for this version already exist
pkgver=$(bash -c "source ${SRC_DIR}/PKGBUILD; echo \${pkgver}")
pkgrel=$(bash -c "source ${SRC_DIR}/PKGBUILD; echo \${pkgrel}")
existing=$(find "${ARTIFACTS_DIR}" -maxdepth 1 \
-name "webkit2gtk-${pkgver}-${pkgrel}-*.pkg.tar.zst" \
! -name 'webkit2gtk-docs-*' \
-print | head -n1)
if [[ -n "${existing}" ]]; then
log "Artifacts for ${pkgver}-${pkgrel} already exist, skipping build"
log "Using cached: $(basename "${existing}")"
exit 0
fi
# Clean any leftover build artifacts from a previous run # Clean any leftover build artifacts from a previous run
log "Cleaning previous build artifacts in ${SRC_DIR}" log "Cleaning previous build artifacts in ${SRC_DIR}"
# makepkg leaves behind src/, pkg/ and the .pkg.tar.zst files # makepkg leaves behind src/, pkg/ and the .pkg.tar.zst files
+1 -1
View File
@@ -73,7 +73,7 @@ log "Running publish"
if "${SCRIPT_DIR}/publish.sh"; then if "${SCRIPT_DIR}/publish.sh"; then
log "Publish succeeded" log "Publish succeeded"
else else
log "ERROR: Publish failed" log "ERROR: Publish failed, exit code: $?"
exit 1 exit 1
fi fi
+18 -6
View File
@@ -8,6 +8,16 @@
set -euo pipefail set -euo pipefail
# Load .env so all variables are available both here (root) and in child
# processes running as builduser. Docker's env_file only sets variables for
# the initial process; sudo drops them by default.
if [[ -f /workspace/.env ]]; then
set -a
# shellcheck source=/dev/null
source /workspace/.env
set +a
fi
POLL_INTERVAL_SECONDS="${POLL_INTERVAL_SECONDS:-3600}" POLL_INTERVAL_SECONDS="${POLL_INTERVAL_SECONDS:-3600}"
# Set up AUR SSH key # Set up AUR SSH key
@@ -25,21 +35,21 @@ else
fi fi
# Set git identity for builduser # Set git identity for builduser
sudo -u builduser git config --global user.name "${AUR_MAINTAINER_NAME:-webkit2gtk-automator}" sudo -u builduser HOME=/home/builduser git config --global user.name "${AUR_MAINTAINER_NAME:-webkit2gtk-automator}"
sudo -u builduser git config --global user.email "${AUR_MAINTAINER_EMAIL:-noreply@localhost}" sudo -u builduser HOME=/home/builduser git config --global user.email "${AUR_MAINTAINER_EMAIL:-noreply@localhost}"
# Import WebKitGTK PGP signing keys into builduser's keyring # Import WebKitGTK PGP signing keys into builduser's keyring
# makepkg verifies the source tarball signature against these keys. # makepkg verifies the source tarball signature against these keys.
# Try the bundled local keys first (no network needed), then fall back to keyservers. # Try the bundled local keys first (no network needed), then fall back to keyservers.
echo "[entrypoint] Importing WebKitGTK PGP signing keys" echo "[entrypoint] Importing WebKitGTK PGP signing keys"
if ls /workspace/webkit2gtk/keys/pgp/*.asc &>/dev/null; then if ls /workspace/webkit2gtk/keys/pgp/*.asc &>/dev/null; then
sudo -u builduser gpg --import /workspace/webkit2gtk/keys/pgp/*.asc sudo -u builduser HOME=/home/builduser gpg --import /workspace/webkit2gtk/keys/pgp/*.asc
echo "[entrypoint] PGP keys imported from local bundle" echo "[entrypoint] PGP keys imported from local bundle"
else else
sudo -u builduser gpg --keyserver keyserver.ubuntu.com --recv-keys \ sudo -u builduser HOME=/home/builduser gpg --keyserver keyserver.ubuntu.com --recv-keys \
5AA3BC334FD7E3369E7C77B291C559DBE4C9123B \ 5AA3BC334FD7E3369E7C77B291C559DBE4C9123B \
013A0127AC9C65B34FFA62526C1009B693975393 || \ 013A0127AC9C65B34FFA62526C1009B693975393 || \
sudo -u builduser gpg --keyserver hkps://keys.openpgp.org --recv-keys \ sudo -u builduser HOME=/home/builduser gpg --keyserver hkps://keys.openpgp.org --recv-keys \
5AA3BC334FD7E3369E7C77B291C559DBE4C9123B \ 5AA3BC334FD7E3369E7C77B291C559DBE4C9123B \
013A0127AC9C65B34FFA62526C1009B693975393 013A0127AC9C65B34FFA62526C1009B693975393
echo "[entrypoint] PGP keys imported from keyserver" echo "[entrypoint] PGP keys imported from keyserver"
@@ -47,9 +57,11 @@ fi
# Drop to builduser and start the polling loop # Drop to builduser and start the polling loop
echo "[entrypoint] Starting polling loop, interval: ${POLL_INTERVAL_SECONDS}s" echo "[entrypoint] Starting polling loop, interval: ${POLL_INTERVAL_SECONDS}s"
exec sudo -u builduser bash -c ' exec sudo -u builduser --preserve-env HOME=/home/builduser bash -c '
set -euo pipefail set -euo pipefail
POLL_INTERVAL_SECONDS="'"${POLL_INTERVAL_SECONDS}"'" POLL_INTERVAL_SECONDS="'"${POLL_INTERVAL_SECONDS}"'"
NPROC="'"${NPROC:-}"'"
[[ -n "${NPROC}" ]] && export NPROC
while true; do while true; do
/workspace/scripts/check-update.sh /workspace/scripts/check-update.sh
echo "[entrypoint] Sleeping for ${POLL_INTERVAL_SECONDS}s" echo "[entrypoint] Sleeping for ${POLL_INTERVAL_SECONDS}s"
+14 -15
View File
@@ -33,23 +33,18 @@ die() {
: "${AUR_MAINTAINER_EMAIL:?AUR_MAINTAINER_EMAIL is not set}" : "${AUR_MAINTAINER_EMAIL:?AUR_MAINTAINER_EMAIL is not set}"
# Authenticate gh CLI # Authenticate gh CLI
echo "${GITHUB_TOKEN}" | gh auth login --with-token # GITHUB_TOKEN is already in the environment and picked up by gh automatically
# Find the main webkit2gtk package (not -docs) # Find the main webkit2gtk package only (exclude -docs and -debug variants)
log "Looking for built package in ${ARTIFACTS_DIR}" log "Looking for built package in ${ARTIFACTS_DIR}"
# We want webkit2gtk-<ver>-<rel>-x86_64.pkg.tar.zst, NOT webkit2gtk-docs-*
pkg_file=$(find "${ARTIFACTS_DIR}" -maxdepth 1 \
-name 'webkit2gtk-*.pkg.tar.zst' \
! -name 'webkit2gtk-docs-*' \
-print | sort -V | tail -n1)
[[ -n "${pkg_file}" ]] || die "No webkit2gtk .pkg.tar.zst found in ${ARTIFACTS_DIR}"
log "Found package: ${pkg_file}"
# Derive version from the built PKGBUILD
pkgver=$(bash -c "source ${SRC_PKGBUILD}; echo \${pkgver}") pkgver=$(bash -c "source ${SRC_PKGBUILD}; echo \${pkgver}")
pkgrel=$(bash -c "source ${SRC_PKGBUILD}; echo \${pkgrel}") pkgrel=$(bash -c "source ${SRC_PKGBUILD}; echo \${pkgrel}")
full_version="${pkgver}-${pkgrel}" full_version="${pkgver}-${pkgrel}"
log "Package version: ${full_version}" log "Package version: ${full_version}"
pkg_file="${ARTIFACTS_DIR}/webkit2gtk-${pkgver}-${pkgrel}-x86_64.pkg.tar.zst"
[[ -f "${pkg_file}" ]] || die "Expected artifact not found: ${pkg_file}"
log "Found package: ${pkg_file}"
# Compute sha256sum of the artifact # Compute sha256sum of the artifact
sha256=$(sha256sum "${pkg_file}" | awk '{print $1}') sha256=$(sha256sum "${pkg_file}" | awk '{print $1}')
log "sha256sum: ${sha256}" log "sha256sum: ${sha256}"
@@ -61,12 +56,16 @@ release_title="webkit2gtk ${full_version}"
log "Creating/updating GitHub release ${release_tag}" log "Creating/updating GitHub release ${release_tag}"
# Create the release if it doesn't exist; ignore error if it already does # Create the release if it doesn't exist
gh release create "${release_tag}" \ if gh release view "${release_tag}" --repo "${GITHUB_REPO}" &>/dev/null; then
log "Release ${release_tag} already exists, proceeding to upload asset"
else
log "Creating GitHub release ${release_tag}"
gh release create "${release_tag}" \
--repo "${GITHUB_REPO}" \ --repo "${GITHUB_REPO}" \
--title "${release_title}" \ --title "${release_title}" \
--notes "Automated build of webkit2gtk ${full_version}" \ --notes "Automated build of webkit2gtk ${full_version}"
2>/dev/null || log "Release ${release_tag} already exists, proceeding to upload asset" fi
# Upload the package (--clobber overwrites an existing asset with the same name) # Upload the package (--clobber overwrites an existing asset with the same name)
log "Uploading ${pkg_filename} to release ${release_tag}" log "Uploading ${pkg_filename} to release ${release_tag}"
View File