Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00c89f23f0
|
||
|
|
3b1e7d1982
|
||
|
|
6a708c0303
|
||
|
|
0cdaa6f82d
|
||
|
|
5735859179
|
||
|
|
e57143c4bc
|
||
|
|
3275ec9845
|
||
|
|
b68623a782
|
||
|
|
88e73bbc22
|
||
|
|
025082a92f
|
||
|
|
699ed6a935
|
||
|
|
e63f9cb14f
|
||
|
|
c5c7ab9b8b
|
||
|
|
03f0ca05e0
|
||
|
|
5299b90bbc
|
||
|
|
55b66a1373
|
||
|
|
504a568570
|
||
|
|
0ae2f036b7
|
||
|
|
0e57df4360
|
||
|
|
da26e88147
|
||
|
|
f06bfd1512
|
||
|
|
a940d91794
|
||
|
|
9af4bc6c27
|
||
|
|
3c540f8bed
|
||
|
|
3f3bba05f3
|
||
|
|
01913f7682
|
||
|
|
f9a2978517
|
||
|
|
1e8a1e3282
|
||
|
|
db83549996
|
||
|
|
59d82f06f5
|
@@ -101,6 +101,36 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Trust cachyos and chaotic-aur signing keys
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# The profile's pacman.conf verifies [cachyos] and [chaotic-aur]
|
||||
# signatures (SigLevel inherited from [options]); mkarchiso's
|
||||
# pacstrap checks them against the host keyring.
|
||||
# F3B607488DB35A47 CachyOS <admin@cachyos.org>
|
||||
# 3056513887B78AEB chaotic-aur (Pedro Henrique Lara Campos)
|
||||
for key in F3B607488DB35A47 3056513887B78AEB; do
|
||||
if pacman-key --list-keys "$key" >/dev/null 2>&1; then
|
||||
echo " ✅ $key already in the keyring"
|
||||
else
|
||||
got=0
|
||||
# Retry: gateway drops UDP/53 in bursts (see run 131)
|
||||
for try in 1 2 3 4 5; do
|
||||
if pacman-key --recv-keys "$key" --keyserver keyserver.ubuntu.com; then
|
||||
got=1
|
||||
break
|
||||
fi
|
||||
echo " ⚠️ recv-keys $key failed (attempt $try/5), retrying in $(( try * 15 ))s..." >&2
|
||||
sleep $(( try * 15 ))
|
||||
done
|
||||
if [ "$got" -ne 1 ]; then
|
||||
echo "❌ Could not fetch signing key $key" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
pacman-key --lsign-key "$key"
|
||||
done
|
||||
|
||||
- name: Ensure /dev/fd symlinks exist for mkinitcpio and procsub
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -132,6 +162,23 @@ jobs:
|
||||
rmdir "$d"
|
||||
trap - EXIT
|
||||
|
||||
- name: Require CAP_SETFCAP for file capabilities
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Without CAP_SETFCAP, pacstrap cannot restore security.capability
|
||||
# xattrs ("unable to set CAP_SETFCAP effective capability"), so the
|
||||
# live ISO silently ships newuidmap/newgidmap, snap-confine, dumpcap,
|
||||
# kwin_wayland, ... without their capabilities. Fix the runner
|
||||
# (e.g. allow CAP_SETFCAP in the gitea-runner service) rather than
|
||||
# building a broken image.
|
||||
eff="$(awk '/^CapEff:/{print $2}' /proc/self/status)"
|
||||
if (( (16#$eff >> 31) & 1 )); then
|
||||
echo "✅ CAP_SETFCAP is available (CapEff=$eff)"
|
||||
else
|
||||
echo "❌ CAP_SETFCAP missing (CapEff=$eff) - file capabilities would be dropped from the ISO" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build Arch ISO
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -503,13 +550,11 @@ jobs:
|
||||
url="$GITEA_ORIGIN/$REPOSITORY/releases/download/$TAG_NAME/$enc_fname"
|
||||
downloaded=0
|
||||
for attempt in 1 2 3; do
|
||||
# Try header auth, then ?token=, then anonymous (public repo).
|
||||
# Try header auth, then anonymous (public repo). No ?token=
|
||||
# fallback: a token in the query string lands in access logs.
|
||||
if curl -sfL --max-time 600 -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$url" -o "$tmpdir/$fname"; then
|
||||
downloaded=1
|
||||
elif curl -sfL --max-time 600 "$url?token=$GITEA_TOKEN" \
|
||||
-o "$tmpdir/$fname"; then
|
||||
downloaded=1
|
||||
elif curl -sfL --max-time 600 "$url" -o "$tmpdir/$fname"; then
|
||||
downloaded=1
|
||||
fi
|
||||
@@ -572,8 +617,11 @@ jobs:
|
||||
# Unmount any leftover loop devices or bind mounts in the work directory
|
||||
$PRIV umount -R "$PWD/work" 2>/dev/null || true
|
||||
|
||||
# Clean up loop devices if any remain attached to the work dir
|
||||
$PRIV losetup -D || true
|
||||
# Detach only loop devices backed by files in our work dir:
|
||||
# `losetup -D` would detach every loop device on the runner host.
|
||||
$PRIV losetup -nO NAME,BACK-FILE 2>/dev/null \
|
||||
| awk -v w="$PWD/work/" 'index($2, w) == 1 {print $1}' \
|
||||
| while read -r dev; do $PRIV losetup -d "$dev" || true; done
|
||||
|
||||
# Remove working directories with proper permissions
|
||||
$PRIV rm -rf "$PWD/work"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Upstream pin check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 6 * * 1" # Mondays 06:00 UTC — catches upstream/Qt drift between ISO builds
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- "localrepo/end4-pkgbuilds/quickshell-git/PKGBUILD"
|
||||
- "localrepo/check-quickshell-pin.sh"
|
||||
- "airootfs/root/customize_airootfs.sh"
|
||||
- ".gitea/workflows/pin-check.yaml"
|
||||
|
||||
jobs:
|
||||
quickshell-pin:
|
||||
runs-on: archlinux
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Tripwire for the failure mode that broke ISO build run 137:
|
||||
# a quickshell pin (ours or end-4's) that predates a Qt compat fix
|
||||
# or has simply gone stale. Fails the job so the drift is visible
|
||||
# in Actions instead of surfacing as a 3-hour ISO build failure.
|
||||
- name: Check quickshell pins
|
||||
run: ./localrepo/check-quickshell-pin.sh
|
||||
+76
-16
@@ -5,6 +5,12 @@ on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
# This job rewrites the runner's shared /etc/pacman.conf - never let two
|
||||
# runs do that at the same time.
|
||||
concurrency:
|
||||
group: host-pacman-conf
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: archlinux
|
||||
@@ -56,14 +62,12 @@ jobs:
|
||||
|
||||
- name: Set up CachyOS repo
|
||||
run: |
|
||||
# Key straight from the keyserver; no pinned keyring/mirrorlist
|
||||
# package URLs (they 404 once the mirror prunes that version, and
|
||||
# the mirrorlist was overwritten below anyway).
|
||||
pacman-key --recv-keys F3B607488DB35A47 --keyserver keyserver.ubuntu.com
|
||||
pacman-key --lsign-key F3B607488DB35A47
|
||||
|
||||
pacman -U --noconfirm \
|
||||
'https://mirror.cachyos.org/repo/x86_64/cachyos/cachyos-keyring-20240331-1-any.pkg.tar.zst' \
|
||||
'https://mirror.cachyos.org/repo/x86_64/cachyos/cachyos-mirrorlist-27-1-any.pkg.tar.zst'
|
||||
|
||||
# Fix the mirrorlist URL (pacnew has wrong format)
|
||||
printf '%s\n' 'Server = https://mirror.cachyos.org/repo/$arch/$repo' \
|
||||
> /etc/pacman.d/cachyos-mirrorlist
|
||||
|
||||
@@ -112,10 +116,16 @@ jobs:
|
||||
- name: Lint shell scripts with ShellCheck
|
||||
run: |
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo " Running ShellCheck on all .sh files"
|
||||
echo " Running ShellCheck on all bash scripts"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
|
||||
SH_FILES=$(find . -name '*.sh' -not -path './.git/*')
|
||||
# *.sh plus extensionless bash scripts (alvin-install, choose-mirror,
|
||||
# livecd-sound, ...) picked up by their shebang
|
||||
SH_FILES=$(
|
||||
find . -name '*.sh' -not -path './.git/*'
|
||||
find airootfs/usr/local/bin -type f ! -name '*.sh' \
|
||||
-exec grep -lE '^#!(/usr/bin/env bash|/bin/bash)' {} +
|
||||
)
|
||||
if [ -z "$SH_FILES" ]; then
|
||||
echo "No shell scripts found."
|
||||
exit 0
|
||||
@@ -258,10 +268,18 @@ jobs:
|
||||
done
|
||||
|
||||
# 2) Check localrepo/ for a pre-built .pkg.tar.zst
|
||||
if [[ $MATCHED -eq 0 ]] && compgen -G "localrepo/${pkg}-*.pkg.tar.zst" > /dev/null 2>&1; then
|
||||
# Exact name: strip -<pkgver>-<pkgrel>-<arch>.pkg.tar.zst, so
|
||||
# "foo" is not satisfied by foo-bar-1.0-1-any.pkg.tar.zst
|
||||
if [[ $MATCHED -eq 0 ]]; then
|
||||
for f in localrepo/"${pkg}"-*.pkg.tar.zst; do
|
||||
b=${f##*/}
|
||||
if [[ "${b%-*-*-*}" == "$pkg" ]]; then
|
||||
MATCHED=1
|
||||
FOUND=$((FOUND + 1))
|
||||
echo "📦 LOCAL: $pkg (pre-built in localrepo/)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# 3) Check build-end4-deps.sh for the package name
|
||||
@@ -309,23 +327,65 @@ jobs:
|
||||
echo " Checking for conflicting packages in packages.x86_64"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
|
||||
# Collect all package names from the list
|
||||
# Resolve against the repos mkarchiso sees, including [local-aur]
|
||||
# (localrepo/), so conflicts between pre-built AUR packages and
|
||||
# anything else are caught here instead of in the ISO build.
|
||||
# A fresh dbpath = empty local db, like pacstrap's target root:
|
||||
# packages installed on the runner can neither mask a conflict
|
||||
# nor cause a false one.
|
||||
CONF=$(mktemp)
|
||||
DB=$(mktemp -d)
|
||||
ROOT=$(mktemp -d)
|
||||
cp /etc/pacman.conf "$CONF"
|
||||
printf '\n[local-aur]\nSigLevel = Optional TrustAll\nServer = file://%s/localrepo\n' \
|
||||
"$PWD" >> "$CONF"
|
||||
mkdir -p "$DB/sync"
|
||||
cp -p /var/lib/pacman/sync/*.db "$DB/sync/"
|
||||
pac() { pacman --config "$CONF" --dbpath "$DB" "$@"; }
|
||||
pac -Sy --noconfirm
|
||||
# From here on never download (set after -Sy, which needs to fetch
|
||||
# the file:// local-aur db): the check only needs a prepared
|
||||
# transaction
|
||||
sed -i '/^\[options\]/a XferCommand = /usr/bin/false %u' "$CONF"
|
||||
|
||||
# Packages built at ISO build time (build-end4-deps.sh) can't be
|
||||
# resolved yet; everything else must be
|
||||
mapfile -t AVAIL < <(pac -Slq | sort -u)
|
||||
PKGS=()
|
||||
while IFS= read -r pkg; do
|
||||
[[ -z "$pkg" || "$pkg" =~ ^# ]] && continue
|
||||
if printf '%s\n' "${AVAIL[@]}" | grep -qxF -- "$pkg"; then
|
||||
PKGS+=("$pkg")
|
||||
else
|
||||
echo "⚠️ Skipping unresolvable package: $pkg"
|
||||
fi
|
||||
done < packages.x86_64
|
||||
|
||||
# Use pacman -Sp --print to resolve the full install set and check for conflicts
|
||||
# This catches "X and Y are in conflict" errors before the ISO build
|
||||
PKG_LIST=$(printf '%s\n' "${PKGS[@]}")
|
||||
if CONFLICTS=$(echo "$PKG_LIST" | pacman -Sp --needed - 2>&1); then
|
||||
echo "✅ No package conflicts detected"
|
||||
# `pacman -Sp` skips conflict checks entirely, so run a real -S
|
||||
# into an empty root. Conflicts and broken deps fail in "prepare",
|
||||
# before any download; a clean list gets as far as the download,
|
||||
# which the XferCommand above makes fail on purpose.
|
||||
if [ ${#PKGS[@]} -eq 0 ]; then
|
||||
echo "✅ No resolvable packages to check."
|
||||
else
|
||||
echo "$CONFLICTS" | grep -i "conflict" || true
|
||||
# pacman exits non-zero either way; judge by its output, not
|
||||
# its status (bash -e would otherwise kill the step silently)
|
||||
OUT=$(pac -S --noconfirm --root "$ROOT" --cachedir "$ROOT" "${PKGS[@]}" 2>&1) || true
|
||||
if grep -q 'failed to prepare transaction' <<< "$OUT"; then
|
||||
echo "------- Pacman Output -------"
|
||||
grep -vE '^(http|file|ftp)' <<< "$OUT" | tail -40
|
||||
echo "-----------------------------"
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo " ❌ Conflicting packages found — fix packages.x86_64"
|
||||
echo " ❌ Conflicting/unresolvable packages — fix packages.x86_64"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
exit 1
|
||||
elif ! grep -q 'Proceed with installation' <<< "$OUT"; then
|
||||
echo "------- Pacman Output -------"
|
||||
tail -40 <<< "$OUT"
|
||||
echo "-----------------------------"
|
||||
echo "❌ pacman stopped before the conflict check completed"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ No package conflicts detected (repos + local-aur)"
|
||||
fi
|
||||
|
||||
@@ -9,3 +9,11 @@ airootfs/opt/localrepo/
|
||||
# Build stamp staged by profiledef.sh at ISO build time (see AGENTS.md);
|
||||
# consumed by customize_airootfs.sh, never committed
|
||||
airootfs/root/.iso-build-stamp
|
||||
|
||||
# makepkg output from localrepo/build-end4-deps.sh (it builds in place):
|
||||
# keep only the PKGBUILDs and hooks under end4-pkgbuilds/
|
||||
localrepo/end4-pkgbuilds/*/*
|
||||
!localrepo/end4-pkgbuilds/*/PKGBUILD
|
||||
!localrepo/end4-pkgbuilds/*/*.hook
|
||||
# repo-add backups
|
||||
localrepo/*.old
|
||||
|
||||
@@ -22,7 +22,7 @@ ISO), so run it after touching `localrepo/` before building.
|
||||
|
||||
## CI Checks (must pass before merge)
|
||||
|
||||
- **ShellCheck**: all `.sh` files checked with `shellcheck -x -s bash`
|
||||
- **ShellCheck**: all `.sh` files, plus extensionless bash scripts in `airootfs/usr/local/bin/` (by shebang), checked with `shellcheck -x -s bash`
|
||||
- **yamllint**: all `.yml`/`.yaml` files (relaxed config)
|
||||
- **packages.x86_64 syntax**: one package per line, no trailing whitespace, `[a-zA-Z0-9._@+\-]+` only
|
||||
- **Package repo check**: every package in `packages.x86_64` must be resolvable via `pacman -Si` in allowed repos (`cachyos`, `extra`, `multilib`, `chaotic-aur`), OR have a pre-built `.pkg.tar.zst` in `localrepo/`, OR appear in `localrepo/build-end4-deps.sh`
|
||||
@@ -53,23 +53,79 @@ install them into the target without the network.
|
||||
| `pacman.conf` | Repos: cachyos → core → extra → multilib → chaotic-aur → local-aur |
|
||||
| `bootstrap_packages` | Minimal build-time packages (`base`, `arch-install-scripts`) |
|
||||
| `airootfs/root/customize_airootfs.sh` | Runs inside chroot during build: keyrings, skel dotfiles (incl. end4-pC), qsConfig patch, end-4 `install-deps`, package harvest, uv/font pre-warm |
|
||||
| `airootfs/root/.live-pacman.conf` | `/etc/pacman.conf` of the built image (adds `[local-aur]` = `file:///opt/localrepo`) |
|
||||
| `airootfs/usr/local/bin/alvin-install` | Installer: partitions, pacstrap, LUKS (systemd initramfs **or** experimental unl0kr + optional TPM2 unlock), user, git identity + GitHub SSH keys, login manager (none/greetd/sddm/gdm) + autologin, end-4 dotfiles (`--skip-alldeps`), build-stamp motd, boot |
|
||||
| `airootfs/root/.live-pacman.conf` | `/etc/pacman.conf` of the built image (adds `[local-aur]` = `file:///opt/localrepo`); also what pacstrap resolves the target from, so `[cachyos]` must stay ahead of `[core]` like in `pacman.conf` |
|
||||
| `airootfs/usr/local/bin/alvin-install` | Installer: partitions, pacstrap, LUKS (systemd initramfs **or** experimental unl0kr + optional TPM2 unlock), user (fish shell), git identity + GitHub SSH keys, login manager (none/greetd/sddm/gdm) + autologin, optional sshd (default on), end-4 dotfiles (`--skip-alldeps`), boot |
|
||||
| `localrepo/build-end4-deps.sh` | Non-interactive AUR builds for end-4 dependencies |
|
||||
| `localrepo/update.sh` | Regenerates localrepo DB, syncs names to packages.x86_64, syncs `airootfs/opt/localrepo/` |
|
||||
| `localrepo/check-quickshell-pin.sh` | Tripwire: our quickshell pin and end-4's must include the Qt 6.12 fix and stay <45d old (`QUICKSHELL_PIN_MAX_AGE_DAYS` overrides) |
|
||||
| `.gitea/workflows/pin-check.yaml` | Runs the pin check weekly (Mon 06:00), on dispatch, and on pushes touching pins/`customize_airootfs.sh` |
|
||||
|
||||
## alvin-install (installer inside the ISO)
|
||||
|
||||
Source: `airootfs/usr/local/bin/alvin-install` (~1,880 lines, **no `.sh` extension**).
|
||||
The airootfs overlay ships it as `/usr/local/bin/alvin-install` (mode `0755` forced in
|
||||
`profiledef.sh` `file_permissions`), and `/etc/motd` advertises it on the live medium.
|
||||
|
||||
- **Invoke**: as root from the live session. Hard requirements: `gum` and UEFI —
|
||||
`check_prereqs` exits if `/sys/firmware/efi` is missing. Log: `/var/log/alvin-install.log`
|
||||
(copied into the target at the end; `ERR` trap prints the failing line).
|
||||
- **Structure**: `main()` runs 16 `screen_*` TUI functions (collect answers: welcome, keymap,
|
||||
network, disk, luks, unl0kr, filesystem, username, password, hostname, git, timezone,
|
||||
locale, login manager, sshd, summary) then a fixed order of `install_*` steps
|
||||
(partition → LUKS → format/mount → pacstrap → fstab → repos → timezone → locale →
|
||||
hostname → network → sshd → user → git/SSH → end-4 dots → mkinitcpio → bootloader →
|
||||
TPM/unl0kr → login manager (none if unl0kr succeeded; with unl0kr selected the login screen only asks for a fallback) → autologin → update (reflector + keyrings + `pacman -Syu`, warn-only) → cleanup). Screens and install steps are
|
||||
independent — edit one without
|
||||
touching the other. An `EXIT` trap unmounts `$TARGET` and closes `cryptroot` on any exit.
|
||||
- **Package list**: `install_pacstrap` builds the *installed* system's list from the medium's
|
||||
`/run/archiso/bootmnt/arch/pkglist.x86_64.txt` (i.e. `pacman -Q` of the live ISO), so
|
||||
`packages.x86_64` changes flow into installed systems. It drops `PKGS_EXCLUDE`
|
||||
(`archiso mkinitcpio-archiso mkinitcpio-nfs-utils syslinux memtest86+`) plus names not
|
||||
resolvable in the live repos, then always appends hardcoded essentials
|
||||
(`base linux linux-firmware linux-cachyos networkmanager grub efibootmgr sudo git …`).
|
||||
- **Linting**: CI's shellcheck step picks it up by its bash shebang. Locally:
|
||||
`shellcheck -x -s bash airootfs/usr/local/bin/alvin-install`
|
||||
- end-4 quirks (`--skip-alldeps`, `yes i`, end4-pC re-copy) are in [Gotchas](#gotchas) below.
|
||||
|
||||
## Verify a single change locally (mirrors CI)
|
||||
|
||||
```bash
|
||||
shellcheck -x -s bash <script>.sh # plus the alvin-install command above
|
||||
yamllint -d "{extends: relaxed, rules: {document-start: disable, line-length: disable, new-line-at-end-of-file: disable}}" <file>.yaml
|
||||
```
|
||||
|
||||
`packages.x86_64` syntax: one package per line, `[a-zA-Z0-9._@+\-]+` only, no trailing
|
||||
whitespace.
|
||||
|
||||
A **pre-commit hook** (`githooks/pre-commit`) runs the same ShellCheck pass on every
|
||||
commit, so CI failures surface before you push. Enable it once per clone:
|
||||
|
||||
```bash
|
||||
git config core.hooksPath githooks
|
||||
```
|
||||
|
||||
It skips linting (with a warning) when `shellcheck` is missing rather than blocking the
|
||||
commit; CI remains the enforcer. Bypass it with `git commit --no-verify`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- The profile root is the **repo root** (not a `releng/` subdirectory). The CI build-iso workflow uses `mkarchiso -v -w work -o out/ releng` but this is a naming convention — the actual profile files live at the repo root.
|
||||
- The profile root is the **repo root** (not a `releng/` subdirectory). CI builds with `mkarchiso -v -w "$PWD/work" -o "$PWD/out" -- "$PWD"` (`.gitea/workflows/build-iso.yaml`), and the local build command above does the same — never pass a `releng` path.
|
||||
- `customize_airootfs.sh` clones git repos (oh-my-zsh, lazy.nvim, plugins, end-4 dots) into `/etc/skel` and `/opt` during the ISO build. These require network access at build time but make the live ISO work offline.
|
||||
- `customize_airootfs.sh` runs `./setup install-deps -f -s --skip-plasmaintg` as the throwaway user `ii-builder` (end-4's scripts refuse to run as root) and aborts the build if it fails. `--skip-plasmaintg` is deliberate: that optional Firefox widget pulls 410 packages / 526 MiB of KDE.
|
||||
- The `[local-aur]` repo path in `pacman.conf` (`file:///home/alvin/alvinarch/localrepo`) is for local builds only. The CI does not use this path.
|
||||
- The `[local-aur]` repo path in `pacman.conf` (`file:///home/alvin/AlvinArch/localrepo`) is for local builds only. The CI does not use this path.
|
||||
- The **image** ships its own `[local-aur]` at `file:///opt/localrepo` (see `.live-pacman.conf`). It holds `localrepo/` (copied by CI/`update.sh`) plus everything `install-deps` built. pacstrap runs without `-P`, so the target keeps the stock `/etc/pacman.conf`; `alvin-install` strips `[local-aur]` from it anyway as a safety net, because `/opt/localrepo` exists only on the medium.
|
||||
- `alvin-install` runs end-4 with `--skip-alldeps` — dependencies must come from the ISO. It feeds `yes i` to end-4's failure prompt: inside the installer chroot the medium's `/run` is bind-mounted in, so end-4's `systemctl --machine=…@.host --user enable … --now` lines can never work (and `--now` would start services on the live medium). `install_end4_dots` re-applies the enable-only part (bluetooth, ydotool, i2c module) outside the chroot and reports every step end-4 had to skip. If the end-4 step reports "incomplete", check that `hyprctl`/`quickshell`/the venv were resolvable (harvest) before re-running anything.
|
||||
- `/etc/skel/.cache/uv` + `/etc/skel/.local/share/uv/python` are pre-warmed by the build (~460 MB: CPython 3.12 and the pinned wheel cache) so end-4's `uv venv`/`uv pip install` at install time needs no network.
|
||||
- **end4-pC** (`pctrade/end4-pC`) is the default quickshell config: cloned into `/etc/skel/.config/quickshell/end4-pC` at build time, selected by patching `hl.env("qsConfig", "ii")` → `"end4-pC"` in the **staged** `/opt/dots-hyprland/dots/.config/hypr/hyprland/variables.lua` (there is no `hypr/hyprland/` in this repo — `./setup install` copies it to the installed system). `alvin-install` re-copies end4-pC into the user's home *after* `./setup install`, because end-4's installer `rsync --delete`s all of `~/.config/quickshell`.
|
||||
- `airootfs/etc/skel/.config/illogical-impulse/presets/` carries the user's presets (`Laptop.json`, `Personal-Performance.json`, `Personal-Performance.zip`). They embed `/home/alvin/...` paths, so wallpapers/screenshots need fixing up after install.
|
||||
- End-4 metapackages are built from `localrepo/end4-pkgbuilds/` (quickshell-git, bibata-modern-classic-bin, microtex-git).
|
||||
- **quickshell pin / Qt 6.12**: end-4 pins quickshell to `41651d7` (Sep 25), which predates upstream fix `5d5d498` (Oct 3, *"use MOC includes instead of opaque pointer definitions — … Qt 6.12 compatibility"*). Arch shipped qt6 6.12.0 on Oct 8 and the old pin died with `Meta Types must be fully defined` in the moc build of quickshell-hyprland-ipc (failed CI run 137). `customize_airootfs.sh` therefore rewrites end-4's `_commit` to `11ca60be` after cloning — but **only** while it still matches `^_commit='41651d7`, so once end-4 bumps their own pin the guard goes inert and theirs wins. `localrepo/check-quickshell-pin.sh` (weekly `pin-check.yaml` job) fails CI if either pin goes stale or loses the fix; it warns instead of failing when end-4's known-stale pin is covered by the override.
|
||||
- **MicroTeX flags**: the image's `makepkg.conf` is CachyOS's (`-march=native -O3`, LTO). GCC 16.2 hit an internal compiler error (segfault) on MicroTeX's `gtkmm_main.cpp` with it (failed CI run 155; not reproducible locally), so `customize_airootfs.sh` patches end-4's `illogical-impulse-microtex-git` PKGBUILD to `options=(!lto)` + `-O2` (our `localrepo/end4-pkgbuilds/microtex-git` carries the same).
|
||||
- **CAP_SETFCAP on the runner**: without it pacstrap drops `security.capability` xattrs (newuidmap/newgidmap, snap-confine, dumpcap, kwin_wayland, ...) from the live ISO with only a warning. `build-iso.yaml` fails the job early if the runner lacks it — fix the runner, don't remove the check.
|
||||
- **yay SIGSEGV on exit**: yay 13 (libalpm via purego/`dyalpm`) can segfault in `alpm_release()` *after* a finished transaction (failed CI run at end-4's `illogical-impulse-kde` step), which aborted `install-deps`. `customize_airootfs.sh` puts a temporary `yay` shim first on the builder's `PATH`: a failed plain `yay -S <pkgs>` counts as success only if `pacman -T` confirms every target is installed (it logs `[yay-shim]`). Every other failure keeps yay's exit code.
|
||||
- **gvfs / dead `~/.gvfs`**: `install_end4_dots` replays end-4's gsettings writes via `dbus-run-session` as the target user. A session bus D-Bus-activates gvfsd → gvfsd-fuse mounts `~/.gvfs` and dies with the bus, leaving a dead FUSE mount that root can't stat, so the home's catch-all `chown -R` failed (`cannot access '/mnt/home/<user>/.gvfs': Permission denied`) and aborted the install before the bootloader. The replay therefore runs with `GIO_USE_VFS=local GVFS_DISABLE_FUSE=1`, and the function unmounts anything mounted under the home before that chown — keep both.
|
||||
- mono's `cert-sync` runs before `ca-certificates.crt` exists during pacstrap, so `customize_airootfs.sh` (live) and `install_pacstrap` (target) re-run it.
|
||||
- `/etc/skel/.zshrc` is owned by `grml-zsh-config`, so ours is staged as `airootfs/root/.zshrc-skel` and installed by `customize_airootfs.sh` after pacstrap — never add files under `airootfs/` at paths a package owns, or pacstrap aborts with "exists in filesystem".
|
||||
- `packages.x86_64` is sorted alphabetically. Keep it sorted when adding/removing entries.
|
||||
- `airootfs/opt/localrepo/` is a build artifact (gitignored) — never commit it.
|
||||
- **Build stamp flow**: `profiledef.sh` (sourced by mkarchiso) stages the gitignored `airootfs/root/.iso-build-stamp` when a `.git` dir exists **or** `CI`/`GITEA_ACTIONS` is set — line reads `AlvinArch build <date> | commit <date> | <4-char hash>` (falls back to `commit unknown` if `git -c safe.directory` can't read the repo; without `.git`/CI no file is staged). `customize_airootfs.sh` installs it as `/etc/alvin-build-stamp` on the live medium, and `alvin-install`'s `install_motd` copies the live `/etc/motd` banner to the target and appends the stamp. If the medium has no stamp, the installed system gets no motd from us.
|
||||
- **Build stamp flow**: `profiledef.sh` (sourced by mkarchiso) stages the gitignored `airootfs/root/.iso-build-stamp` when a `.git` dir exists **or** `CI`/`GITEA_ACTIONS` is set — line reads `AlvinArch build <date> | commit <date> | <4-char hash>` (falls back to `commit unknown` if `git -c safe.directory` can't read the repo; without `.git`/CI no file is staged). `customize_airootfs.sh` keeps it as `/etc/alvin-build-stamp` on the live medium **and appends it to the live `/etc/motd`**, so the booted ISO identifies its build. The installed system's motd is never touched by us — `alvin-install` has no motd step (an earlier `install_motd` that copied the banner + stamp into the target was removed on purpose).
|
||||
|
||||
@@ -21,7 +21,6 @@ AlvinArch/
|
||||
├── localrepo/
|
||||
│ ├── build-end4-deps.sh # non-interactive AUR build (all deps)
|
||||
│ ├── end4-pkgbuilds/ # microtex-git, quickshell-git, bibata
|
||||
│ ├── illogical-impulse-quickshell-git-*.pkg.tar.zst
|
||||
│ ├── illogical-impulse-bibata-modern-classic-bin-*.pkg.tar.zst
|
||||
│ └── update.sh # existing, regenerates repo db
|
||||
└── packages.x86_64 # 420 packages (65+ end-4 deps added)
|
||||
@@ -37,9 +36,10 @@ AlvinArch/
|
||||
6. [System Services & Networking](#system-services--networking)
|
||||
7. [Local Repository (localrepo/)](#local-repository-localrepo)
|
||||
8. [Boot Configuration](#boot-configuration)
|
||||
9. [Build & Test](#build--test)
|
||||
10. [Planned Additions](#planned-additions)
|
||||
11. [Troubleshooting](#troubleshooting)
|
||||
9. [Automated Installer (alvin-install)](#automated-installer-alvin-install)
|
||||
10. [Build & Test](#build--test)
|
||||
11. [Planned Additions](#planned-additions)
|
||||
12. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
@@ -50,7 +50,7 @@ AlvinArch/
|
||||
### Key Features
|
||||
|
||||
- **Hyprland + end-4** — Wayland compositor with illogical-impulse dotfiles (quickshell, bibata cursors, microtex)
|
||||
- **Automated installer (`alvin-install`)** — gum TUI: LUKS with systemd initramfs or experimental touchscreen unl0kr, optional TPM2 auto-unlock, GitHub SSH key import, login manager choice (none/greetd/sddm/gdm), autologin, and a build stamp in `/etc/motd`
|
||||
- **Automated installer (`alvin-install`)** — gum TUI: LUKS with systemd initramfs or experimental touchscreen unl0kr, optional TPM2 auto-unlock, GitHub SSH key import, login manager choice (none/greetd/sddm/gdm), optional sshd (on by default), autologin; the build stamp identifies the live ISO via its `/etc/motd`
|
||||
- **LazyVim** — Pre-configured Neovim with lazy.nvim and curated plugins
|
||||
- **Fish + Zsh + Starship** — Dual shell setup with oh-my-zsh and a cross-shell prompt
|
||||
- **Local AUR repo** — Pre-built packages (end-4 deps, wallust, grub-customizer, etc.) that aren't in official repos
|
||||
@@ -138,7 +138,7 @@ AlvinArch/
|
||||
│ │ └── mkinitcpio.conf.d/ # archiso initramfs config
|
||||
│ ├── usr/
|
||||
│ │ ├── lib/os-release # usr-merge os-release
|
||||
│ │ ├── local/bin/ # choose-mirror, Installation_guide, livecd-sound
|
||||
│ │ ├── local/bin/ # alvin-install, choose-mirror, Installation_guide, livecd-sound
|
||||
│ │ ├── local/share/livecd-sound/ # ALSA config (asound.conf.in)
|
||||
│ │ └── share/pacman/keyrings/ # CachyOS GPG keyring + trust data
|
||||
│ └── root/
|
||||
@@ -152,7 +152,7 @@ AlvinArch/
|
||||
│ ├── update.sh # Regenerates repo DB + syncs names to packages.x86_64
|
||||
│ ├── end4-pkgbuilds/ # PKGBUILDs: quickshell-git, microtex-git, bibata-modern-classic-bin
|
||||
│ ├── *.pkg.tar.zst # Pre-built packages (illogical-impulse-*, wallust, grub-customizer,
|
||||
│ │ # snapd, upscayl, meshy-git, pacserve, etc.)
|
||||
│ │ # snapd, upscayl, eternalterminal, etc.)
|
||||
│ └── local-aur.db{,.tar.gz} # Repo database files
|
||||
├── efiboot/ # UEFI boot (systemd-boot)
|
||||
│ └── loader/
|
||||
@@ -230,7 +230,7 @@ Cross-shell prompt config for [Starship](https://starship.rs/). Works with both
|
||||
|
||||
### **.zshrc / .fzf.zsh**
|
||||
|
||||
Zsh configuration adapted for oh-my-zsh (installed by `customize_airootfs.sh`) and fzf shell integration.
|
||||
Zsh configuration adapted for oh-my-zsh (installed by `customize_airootfs.sh`) and fzf shell integration. fish is the default login shell; zsh is there if you `chsh` to it. The `.zshrc` source lives at `airootfs/root/.zshrc-skel`, because grml-zsh-config owns `/etc/skel/.zshrc` and shipping it under `airootfs/etc/skel/` would abort the build. zsh-autocomplete is cloned but disabled; see [Troubleshooting](#zsh-autocomplete-partial-load-error).
|
||||
|
||||
---
|
||||
|
||||
@@ -285,7 +285,7 @@ Custom PKGBUILDs for end-4 metapackages:
|
||||
|
||||
### Pre-built Packages
|
||||
|
||||
Packages like `illogical-impulse-quickshell-git`, `illogical-impulse-bibata-modern-classic-bin`, `wallust`, `grub-customizer`, `snapd`, `upscayl-bin`, `meshy-git`, `xwaylandvideobridge`, `pacserve`, etc.
|
||||
Packages like `illogical-impulse-bibata-modern-classic-bin`, `wallust`, `grub-customizer`, `snapd`, `upscayl-bin`, `xwaylandvideobridge`, `eternalterminal`, etc.
|
||||
|
||||
---
|
||||
|
||||
@@ -305,6 +305,66 @@ Legacy BIOS boot with custom splash screen. Includes PXE network boot config.
|
||||
|
||||
---
|
||||
|
||||
## Automated Installer (alvin-install)
|
||||
|
||||
The ISO ships an interactive installer at `/usr/local/bin/alvin-install` (source:
|
||||
`airootfs/usr/local/bin/alvin-install`, ~1,880 lines of bash; the live `/etc/motd`
|
||||
advertises it). It partitions, encrypts, installs, and fully configures a system —
|
||||
including the end-4 dotfiles — without network access to this repo.
|
||||
|
||||
### Running it
|
||||
|
||||
```bash
|
||||
alvin-install # as root on the live medium (root autologins on tty1)
|
||||
```
|
||||
|
||||
Requirements: **UEFI boot** (it exits if `/sys/firmware/efi` is missing — BIOS/CSM
|
||||
is not supported by the installer) and `gum`. A network connection is required and
|
||||
verified by pinging `archlinux.org` before any disk is touched; the network screen
|
||||
can open `nmtui` for WiFi. Every step is logged to `/var/log/alvin-install.log`,
|
||||
which is copied into the installed system.
|
||||
|
||||
### What it asks (gum TUI screens)
|
||||
|
||||
Keymap → network → target disk (the live USB is hidden from the list) → LUKS
|
||||
encryption (optional; **the LUKS passphrase is the same as your login password**)
|
||||
→ experimental unl0kr touchscreen unlock → filesystem (`ext4`/`btrfs`) →
|
||||
username/password/hostname → git identity + GitHub username (both optional) →
|
||||
timezone/locale → login manager → SSH server (enabled by default) → summary.
|
||||
|
||||
### What it does
|
||||
|
||||
1. GPT partitioning (1 GiB ESP) on the chosen disk, optional LUKS2 on the rest,
|
||||
format + mount at `/mnt`
|
||||
2. `pacstrap` with the package list derived from the medium's
|
||||
`pkglist.x86_64.txt` (`pacman -Q` of the live ISO) — `archiso`, `syslinux`,
|
||||
`memtest86+` etc. are dropped, hardcoded essentials (kernel, GRUB,
|
||||
NetworkManager, cryptsetup, microcode) always appended
|
||||
3. User account, sudo, git config, GitHub SSH keys (`ssh-import-id`, falling
|
||||
back to `github.com/<user>.keys`)
|
||||
4. end-4 dotfiles from the staged `/opt/dots-hyprland` via
|
||||
`./setup install -f -s --skip-alldeps`
|
||||
5. Initramfs in one of two modes: **Mode A** — systemd initramfs + `sd-encrypt`
|
||||
(default); **Mode B** — busybox hooks + unl0kr touchscreen unlock
|
||||
(experimental, mutually exclusive with TPM2; falls back to Mode A on failure)
|
||||
6. Optional **TPM2 auto-unlock** (`systemd-cryptenroll`, PCR 0+7; passphrase
|
||||
slot kept as fallback; warns if Secure Boot is off)
|
||||
7. GRUB (UEFI, boot entry `ALVIN`), login manager — `none` (plain tty, Hyprland
|
||||
autostarts), `greetd`+tuigreet, `sddm`, or `gdm` — falls back to `none` only
|
||||
if the **package** can't be resolved/installed; a failed `systemctl enable`
|
||||
keeps `getty@tty1` as the login path (the summary still reports the chosen
|
||||
manager). Optional autologin (forced off when TPM2 is enrolled), and sshd
|
||||
enabled at boot when selected (default: on) — Arch's stock config allows
|
||||
**password login with the same password as LUKS**, so only accept the default
|
||||
on networks you trust (or harden `sshd_config` afterwards). The final banner
|
||||
reports whether the enable actually succeeded, not just what was selected
|
||||
|
||||
On failure an `EXIT` trap unmounts `/mnt` and closes the `cryptroot` mapping, so
|
||||
re-running is safe. If the end-4 step reports "incomplete", see the repository's
|
||||
`AGENTS.md` Gotchas for the chroot/systemd limitations that cause it.
|
||||
|
||||
---
|
||||
|
||||
## Build & Test
|
||||
|
||||
### Building the ISO
|
||||
@@ -324,11 +384,25 @@ sudo mkarchiso -v -w work -o out/ .
|
||||
|
||||
### CI Checks (must pass before merge)
|
||||
|
||||
- **ShellCheck**: all `.sh` files checked with `shellcheck -x -s bash`
|
||||
- **ShellCheck**: all `.sh` files, plus extensionless bash scripts in `airootfs/usr/local/bin/`, checked with `shellcheck -x -s bash`
|
||||
- **yamllint**: all `.yml`/`.yaml` files (relaxed config)
|
||||
- **packages.x86_64 syntax**: one package per line, no trailing whitespace, `[a-zA-Z0-9._@+\-]+` only
|
||||
- **Package repo check**: every package in `packages.x86_64` must be resolvable via `pacman -Si` in allowed repos (`cachyos`, `extra`, `multilib`, `chaotic-aur`), OR have a pre-built `.pkg.tar.zst` in `localrepo/`, OR appear in `localrepo/build-end4-deps.sh`
|
||||
|
||||
### Git Hooks
|
||||
|
||||
A pre-commit hook (`githooks/pre-commit`) runs the ShellCheck pass on every commit, so lint failures surface before you push instead of in CI.
|
||||
|
||||
```bash
|
||||
# Enable once per clone
|
||||
git config core.hooksPath githooks
|
||||
|
||||
# Bypass the hook for a single commit
|
||||
git commit --no-verify
|
||||
```
|
||||
|
||||
If `shellcheck` is not installed the hook warns and skips rather than blocking the commit; CI remains the enforcer.
|
||||
|
||||
### Recommended VirtualBox Settings (for testing)
|
||||
|
||||
- RAM: 4GB minimum, 8GB recommended
|
||||
@@ -377,6 +451,56 @@ The following dotfiles are not yet included but are planned for future versions:
|
||||
- `customize_airootfs.sh` clones repos at build time — requires network access during `mkarchiso`
|
||||
- Check build logs for git clone failures
|
||||
|
||||
### zsh-autocomplete partial-load error
|
||||
|
||||
Symptom:
|
||||
|
||||
```
|
||||
_autocomplete__history_lines: function not defined
|
||||
_autocomplete__unambiguous: function not defined
|
||||
```
|
||||
|
||||
Cause: zsh-autocomplete was loaded after `compinit` (e.g. via oh-my-zsh
|
||||
`plugins=(...)`), a stale completion dump, or a conflict with
|
||||
zsh-autosuggestions / zsh-history-substring-search. On this ISO `compinit`
|
||||
always runs first: grml-zsh-config's global `/etc/zsh/zshrc` calls it
|
||||
unconditionally before `~/.zshrc` is read.
|
||||
|
||||
The shipped `~/.zshrc` leaves zsh-autocomplete out of `plugins=(...)`. The
|
||||
plugin stays cloned at `~/.oh-my-zsh/custom/plugins/zsh-autocomplete/`
|
||||
either way, just disabled by default.
|
||||
|
||||
**Fix: drop autocomplete (recommended)**
|
||||
|
||||
```bash
|
||||
# 1. Edit ~/.zshrc, remove this line from plugins=(...):
|
||||
# zsh-autocomplete
|
||||
|
||||
# 2. Clear stale dumps (bash avoids zsh's nomatch abort on the glob):
|
||||
bash -c 'rm -f ~/.zcompdump* ~/.cache/zsh/zcompdump*'
|
||||
|
||||
# 3. Restart the shell and verify:
|
||||
exec zsh
|
||||
typeset -f _autocomplete__history_lines >/dev/null && echo "still loaded" || echo "clean"
|
||||
```
|
||||
|
||||
**Fix: keep autocomplete instead**
|
||||
|
||||
```bash
|
||||
# 1. Remove zsh-autocomplete, zsh-autosuggestions and
|
||||
# zsh-history-substring-search from plugins=(...) in ~/.zshrc.
|
||||
|
||||
# 2. Stop the global compinit. `skip_global_compinit=1` in ~/.zshenv does
|
||||
# NOT work here (that is a Debian/Ubuntu /etc/zsh/zshrc convention; grml
|
||||
# ignores it), so remove the package that ships the global zshrc:
|
||||
sudo pacman -R grml-zsh-config
|
||||
|
||||
# 3. At the very top of ~/.zshrc, before oh-my-zsh is sourced:
|
||||
source ~/.oh-my-zsh/custom/plugins/zsh-autocomplete/zsh-autocomplete.plugin.zsh
|
||||
|
||||
# 4. Clear dumps as above, then: exec zsh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# mkinitcpio preset file for the 'linux-cachyos' package on archiso
|
||||
# (the kernel the boot entries load). Not owned by any package: mkinitcpio's
|
||||
# install hook only generates a preset when none exists, so this one wins and
|
||||
# the image gets the archiso initramfs alone - no unused fallback image.
|
||||
|
||||
PRESETS=('archiso')
|
||||
|
||||
ALL_kver='/boot/vmlinuz-linux-cachyos'
|
||||
archiso_config='/etc/mkinitcpio.conf.d/archiso.conf'
|
||||
|
||||
archiso_image="/boot/initramfs-linux-cachyos.img"
|
||||
@@ -1,8 +0,0 @@
|
||||
# mkinitcpio preset file for the 'linux' package on archiso
|
||||
|
||||
PRESETS=('archiso')
|
||||
|
||||
ALL_kver='/boot/vmlinuz-linux'
|
||||
archiso_config='/etc/mkinitcpio.conf.d/archiso.conf'
|
||||
|
||||
archiso_image="/boot/initramfs-linux.img"
|
||||
@@ -33,6 +33,14 @@ LocalFileSigLevel = Optional
|
||||
# - URLs will have $arch replaced by the name of the architecture
|
||||
#
|
||||
|
||||
# [cachyos] first, same as the build's pacman.conf: pacstrap installs the
|
||||
# target from this file, so with [core] ahead the target got Arch builds of
|
||||
# everything cachyos also ships (pacman -2 vs the live -4 -> libalpm
|
||||
# "unknown key '%INSTALLED_DB%'" warnings) and flipped them on the first -Syu.
|
||||
[cachyos]
|
||||
SigLevel = Required DatabaseOptional
|
||||
Include = /etc/pacman.d/cachyos-mirrorlist
|
||||
|
||||
[core]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
@@ -42,10 +50,6 @@ Include = /etc/pacman.d/mirrorlist
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[cachyos]
|
||||
SigLevel = Required DatabaseOptional
|
||||
Include = /etc/pacman.d/cachyos-mirrorlist
|
||||
|
||||
[chaotic-aur]
|
||||
SigLevel = Required DatabaseOptional
|
||||
Include = /etc/pacman.d/chaotic-mirrorlist
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# ~/.zshrc - installed into /etc/skel by customize_airootfs.sh (it replaces
|
||||
# grml-zsh-config's skel copy; grml's global /etc/zsh/zshrc still loads first).
|
||||
|
||||
export ZSH="$HOME/.oh-my-zsh"
|
||||
ZSH_THEME="" # starship draws the prompt
|
||||
zstyle ':omz:update' mode reminder # never auto-pull on startup
|
||||
|
||||
# Plugins are pre-cloned into $ZSH/custom/plugins at ISO build time.
|
||||
# zsh-syntax-highlighting must load before zsh-history-substring-search.
|
||||
# zsh-autocomplete is cloned too but left off: it must load before compinit,
|
||||
# which grml's /etc/zsh/zshrc already ran, and it fights zsh-autosuggestions.
|
||||
# To use it anyway, see README.md "zsh-autocomplete partial-load error".
|
||||
plugins=(
|
||||
git
|
||||
fzf-zsh-plugin
|
||||
zsh-eza
|
||||
zsh-autosuggestions
|
||||
zsh-syntax-highlighting
|
||||
zsh-history-substring-search
|
||||
)
|
||||
|
||||
source "$ZSH/oh-my-zsh.sh"
|
||||
|
||||
bindkey '^[[A' history-substring-search-up
|
||||
bindkey '^[[B' history-substring-search-down
|
||||
|
||||
[[ -f ~/.fzf.zsh ]] && source ~/.fzf.zsh
|
||||
|
||||
if command -v starship >/dev/null 2>&1 && [[ "$TERM" != "linux" ]]; then
|
||||
eval "$(starship init zsh)"
|
||||
fi
|
||||
@@ -28,9 +28,13 @@ install -m 0644 /root/.live-pacman.conf /etc/pacman.conf
|
||||
rm -f /root/.live-pacman.conf
|
||||
|
||||
# Build stamp staged by profiledef.sh (absent for non-git, non-CI builds):
|
||||
# keep it where alvin-install looks for it, drop the staging copy.
|
||||
# keep the stamp file itself as a reference, drop the staging copy, and
|
||||
# stamp the live medium's motd so the booted ISO identifies its build (the
|
||||
# installed system keeps the stock package motd - alvin-install never
|
||||
# writes /etc/motd).
|
||||
if [[ -f /root/.iso-build-stamp ]]; then
|
||||
install -m 0644 /root/.iso-build-stamp /etc/alvin-build-stamp
|
||||
cat /etc/alvin-build-stamp >> /etc/motd
|
||||
rm -f /root/.iso-build-stamp
|
||||
fi
|
||||
|
||||
@@ -68,6 +72,14 @@ for plugin in "${!OMZ_PLUGINS[@]}"; do
|
||||
fi
|
||||
done
|
||||
|
||||
# grml-zsh-config owns /etc/skel/.zshrc, so shipping ours in
|
||||
# airootfs/etc/skel would make pacstrap abort ("exists in filesystem").
|
||||
# Stage it under /root and overwrite the package's copy here, after pacstrap.
|
||||
if [[ -f /root/.zshrc-skel ]]; then
|
||||
install -m 0644 /root/.zshrc-skel "${SKEL}/.zshrc"
|
||||
rm -f /root/.zshrc-skel
|
||||
fi
|
||||
|
||||
# ── LazyVim (lazy.nvim bootstraps on first launch, but pre-clone the plugin) ─
|
||||
NVIM_DATA="${SKEL}/.local/share/nvim"
|
||||
mkdir -p "${NVIM_DATA}"
|
||||
@@ -85,6 +97,34 @@ if [[ ! -d "${DOTS_REPO}/.git" ]]; then
|
||||
git -C "${DOTS_REPO}" submodule update --init --depth=1
|
||||
fi
|
||||
|
||||
# end-4 pins quickshell to 41651d7 (Sep 25), which predates quickshell's
|
||||
# Qt 6.12 fix (5d5d498, Oct 3: "use MOC includes instead of opaque pointer
|
||||
# definitions - Fixes linking issues and Qt 6.12 compatibility"). Arch
|
||||
# shipped qt6 6.12.0 into extra on Oct 8; with the old pin qmetatype.h's
|
||||
# "Meta Types must be fully defined" static_assert kills the moc build of
|
||||
# quickshell-hyprland-ipc (failed CI run 137) and the whole ISO build with
|
||||
# it. Force the fixed commit, but ONLY while end-4 still carries the old
|
||||
# pin - once they bump it themselves the guard stops matching and their
|
||||
# pin wins untouched. localrepo/check-quickshell-pin.sh (weekly CI)
|
||||
# verifies both this pin and end-4's stay Qt 6.12-compatible.
|
||||
QS_PKG="${DOTS_REPO}/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD"
|
||||
if [[ -f "${QS_PKG}" ]] && grep -q "^_commit='41651d7" "${QS_PKG}"; then
|
||||
echo "[customize] Bumping end-4 quickshell pin to 11ca60be (Qt 6.12 fix)..."
|
||||
sed -i "s|^_commit='41651d7[^']*'|_commit='11ca60be22b063478ed9586ca1d7f92f0f261caf'|" "${QS_PKG}"
|
||||
fi
|
||||
|
||||
# GCC 16.2 ICEs (segfault in ggc_set_mark) compiling MicroTeX's gtkmm_main.cpp
|
||||
# - the LaTeX binary the package ships - under CachyOS's makepkg.conf
|
||||
# (-march=native -O3 + -flto=auto), which killed CI run 155. Build it with -O2
|
||||
# and no LTO; MicroTeX is tiny, the flags buy nothing. Re-running is a no-op.
|
||||
MTX_PKG="${DOTS_REPO}/sdata/dist-arch/illogical-impulse-microtex-git/PKGBUILD"
|
||||
if [[ -f "${MTX_PKG}" ]] && ! grep -q '^options=(!lto)' "${MTX_PKG}"; then
|
||||
echo "[customize] Building MicroTeX with -O2 and no LTO (GCC 16 ICE)..."
|
||||
# shellcheck disable=SC2016 # expanded by makepkg, not here
|
||||
sed -i '/^build() {/a\ export CFLAGS="${CFLAGS//-O3/-O2}" CXXFLAGS="${CXXFLAGS//-O3/-O2}"' "${MTX_PKG}"
|
||||
printf '\noptions=(!lto)\n' >> "${MTX_PKG}"
|
||||
fi
|
||||
|
||||
# ── end4-pC: the default quickshell config, shipped in skel ──────────────────
|
||||
# pctrade/end4-pC is a fork of the ii shell config. It lives next to ii in
|
||||
# ~/.config/quickshell and does not modify it; which one runs is decided by
|
||||
@@ -132,6 +172,36 @@ chmod 440 /etc/sudoers.d/99-ii-builder
|
||||
# so the tree must be owned by the account that runs it.
|
||||
chown -R "${BUILD_USER}:${BUILD_USER}" "${DOTS_REPO}"
|
||||
|
||||
# yay 13 (libalpm via purego/dyalpm) can SIGSEGV in alpm_release() at exit,
|
||||
# *after* the transaction and its hooks completed (failed CI run: crash in
|
||||
# dyalpm handle.Release). end-4 sees exit 2 and aborts. This shim, put first
|
||||
# on PATH for the install-deps run only, turns a failed plain `yay -S <pkgs>`
|
||||
# into success when every target is installed afterwards (pacman -T); any
|
||||
# other failure keeps yay's exit code. It lives in /tmp and is removed after.
|
||||
YAY_SHIM_DIR="$(mktemp -d /tmp/ii-yay-shim.XXXXXX)"
|
||||
cat > "${YAY_SHIM_DIR}/yay" <<'EOF'
|
||||
#!/bin/bash
|
||||
"${YAY_SHIM_REAL:-/usr/bin/yay}" "$@"
|
||||
rc=$?
|
||||
(( rc == 0 )) && exit 0
|
||||
sync=0
|
||||
targets=()
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
-S|--sync) sync=1 ;;
|
||||
-S*) exit "$rc" ;; # -Ss/-Si/-Syu/...: not a plain install
|
||||
-*) ;;
|
||||
*) targets+=("$a") ;;
|
||||
esac
|
||||
done
|
||||
if (( sync && ${#targets[@]} )) && pacman -T -- "${targets[@]}" >/dev/null; then
|
||||
echo "[yay-shim] yay exited ${rc}, but all ${#targets[@]} targets are installed - continuing" >&2
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
EOF
|
||||
chmod 755 "${YAY_SHIM_DIR}" "${YAY_SHIM_DIR}/yay"
|
||||
|
||||
# -f: never prompt (ask=false); -s: skip "pacman -Syu";
|
||||
# --skip-plasmaintg: optional Firefox widget that pulls 410 pkgs / 526 MiB of
|
||||
# KDE packages onto a non-KDE system;
|
||||
@@ -140,11 +210,14 @@ chown -R "${BUILD_USER}:${BUILD_USER}" "${DOTS_REPO}"
|
||||
# shellcheck disable=SC2024 # the redirect is meant for the child, not sudo
|
||||
if ! sudo -u "${BUILD_USER}" env HOME="/home/${BUILD_USER}" \
|
||||
GIT_TERMINAL_PROMPT=0 \
|
||||
PATH="${YAY_SHIM_DIR}:/usr/local/sbin:/usr/local/bin:/usr/bin" \
|
||||
bash -c "cd ${DOTS_REPO} && ./setup install-deps -f -s --skip-plasmaintg" \
|
||||
< <(yes e); then
|
||||
rm -rf "${YAY_SHIM_DIR}"
|
||||
echo "[customize] end-4 ./setup install-deps failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -rf "${YAY_SHIM_DIR}"
|
||||
|
||||
# ── Harvest the packages install-deps just built into the in-image local repo ─
|
||||
# The live /etc/pacman.conf points [local-aur] at /opt/localrepo; without the
|
||||
@@ -197,11 +270,13 @@ fi
|
||||
|
||||
# Rebuild the repo database (CI/update.sh ship a pre-built one alongside the
|
||||
# packages) and refresh the live system's copy of it. No network needed: the
|
||||
# remote repos were synced during pacstrap.
|
||||
# remote repos were synced during pacstrap. No -R: the loop above already
|
||||
# deleted the replaced archives, so repo-add's own cleanup only logged a
|
||||
# spurious "Cannot remove file" ERROR.
|
||||
local_pkgs=(/opt/localrepo/*.pkg.tar.zst)
|
||||
if ((${#local_pkgs[@]} > 0)); then
|
||||
echo "[customize] Rebuilding local-aur db (${#local_pkgs[@]} packages)..."
|
||||
repo-add -R /opt/localrepo/local-aur.db.tar.gz "${local_pkgs[@]}"
|
||||
repo-add /opt/localrepo/local-aur.db.tar.gz "${local_pkgs[@]}"
|
||||
mkdir -p /var/lib/pacman/sync
|
||||
cp -fL /opt/localrepo/local-aur.db /var/lib/pacman/sync/local-aur.db
|
||||
if [[ -f /opt/localrepo/local-aur.files ]]; then
|
||||
@@ -209,6 +284,16 @@ if ((${#local_pkgs[@]} > 0)); then
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── mono certificate store ──────────────────────────────────────────────────
|
||||
# mono's post_install runs cert-sync during pacstrap, before the
|
||||
# post-transaction hook has generated ca-certificates.crt, so the store ships
|
||||
# empty ("Couldn't retrieve the file") and mono apps reject every TLS cert.
|
||||
if command -v cert-sync &>/dev/null; then
|
||||
echo "[customize] Populating mono certificate store..."
|
||||
cert-sync --quiet /etc/ssl/certs/ca-certificates.crt \
|
||||
|| echo "[customize] WARNING: cert-sync failed, mono store left empty" >&2
|
||||
fi
|
||||
|
||||
# ── makepkg leftovers + throwaway account do not belong in the ISO ──────────
|
||||
if [[ -d "${DOTS_REPO}/sdata/dist-arch" ]]; then
|
||||
find "${DOTS_REPO}/sdata/dist-arch" -mindepth 2 -maxdepth 2 -type d \
|
||||
@@ -334,18 +419,18 @@ else
|
||||
echo "[customize] uv not found - skipping python/wheel pre-warm."
|
||||
fi
|
||||
|
||||
# ── Fish: ensure default shell is set for the live user ──────────────────────
|
||||
# The live user (usually 'archlinux' or 'root') gets fish as default shell
|
||||
# ── Fish: default shell for the live root user ───────────────────────────────
|
||||
# (alvin-install creates the installed user with fish as well.)
|
||||
if command -v fish &>/dev/null; then
|
||||
echo "[customize] Setting fish as default shell for skel..."
|
||||
echo "[customize] Setting fish as root's shell on the live medium..."
|
||||
chsh -s /usr/bin/fish root 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# ── Ensure skel directories have correct permissions ─────────────────────────
|
||||
chmod 700 "${SKEL}/.config" 2>/dev/null || true
|
||||
find "${SKEL}/.config" -type f -exec chmod 644 {} \; 2>/dev/null || true
|
||||
find "${SKEL}/.config" -type d -exec chmod 755 {} \; 2>/dev/null || true
|
||||
find "${SKEL}/.config" -name '*.sh' -exec chmod 755 {} \; 2>/dev/null || true
|
||||
find "${SKEL}/.local" -type d -exec chmod 755 {} \; 2>/dev/null || true
|
||||
# Only take away group/other write and make everything readable: forcing
|
||||
# files to 644 stripped +x from executables that are not *.sh (python/fish
|
||||
# helpers in the cloned quickshell configs).
|
||||
chmod -R go-w,a+rX "${SKEL}/.config" "${SKEL}/.local" 2>/dev/null || true
|
||||
find "${SKEL}/.config" -name '*.sh' -exec chmod 755 {} + 2>/dev/null || true
|
||||
|
||||
echo "[customize] Dotfile pre-installation complete."
|
||||
File diff suppressed because it is too large
Load Diff
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# pre-commit hook: run ShellCheck on every shell script in the repo.
|
||||
#
|
||||
# This mirrors the CI check in .gitea/workflows/tests.yaml so the local
|
||||
# lint and the CI lint cannot drift apart. Enable it in a clone with:
|
||||
#
|
||||
# git config core.hooksPath githooks
|
||||
|
||||
set -u
|
||||
|
||||
if ! command -v shellcheck >/dev/null 2>&1; then
|
||||
echo "pre-commit: shellcheck not found on PATH, skipping lint." >&2
|
||||
echo "pre-commit: install it with 'pacman -S shellcheck'; CI still enforces it." >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Same file set as CI: *.sh plus the extensionless bash scripts in
|
||||
# airootfs/usr/local/bin picked up by their shebang.
|
||||
# find's stderr is dropped because localrepo/end4-pkgbuilds/*/pkg is left
|
||||
# at mode d--x--x--x by makepkg and prints "Permission denied" locally.
|
||||
sh_files=$(
|
||||
{
|
||||
find . -name '*.sh' -not -path './.git/*' 2>/dev/null
|
||||
find airootfs/usr/local/bin -type f ! -name '*.sh' \
|
||||
-exec grep -lE '^#!(/usr/bin/env bash|/bin/bash)' {} + 2>/dev/null
|
||||
} | sed '/^$/d' | sort -u
|
||||
)
|
||||
|
||||
if [ -z "$sh_files" ]; then
|
||||
echo "pre-commit: no shell scripts found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
failed=0
|
||||
while IFS= read -r f; do
|
||||
if shellcheck -x -s bash "$f"; then
|
||||
echo " ok $f"
|
||||
else
|
||||
echo " FAIL $f" >&2
|
||||
failed=1
|
||||
fi
|
||||
done <<< "$sh_files"
|
||||
|
||||
if [ "$failed" -ne 0 ]; then
|
||||
echo "" >&2
|
||||
echo "pre-commit: ShellCheck failed. Fix the issues above, or bypass with:" >&2
|
||||
echo " git commit --no-verify" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -59,8 +59,12 @@ build_local_pkgbuild() {
|
||||
local pkg_name
|
||||
pkg_name=$(basename "${pkg_dir}")
|
||||
|
||||
if ls "${REPO_DIR}"/illogical-impulse-"${pkg_name}"-*.pkg.tar.zst 1>/dev/null 2>&1; then
|
||||
info "Package already exists in localrepo, skipping: ${pkg_name}"
|
||||
# Skip only while a built package is newer than its PKGBUILD - bumping
|
||||
# e.g. quickshell's _commit must trigger a rebuild, not ship the old one.
|
||||
if [[ -n "$(find "${REPO_DIR}" -maxdepth 1 \
|
||||
-name "illogical-impulse-${pkg_name}-*.pkg.tar.zst" \
|
||||
-newer "${pkg_dir}/PKGBUILD" -print -quit)" ]]; then
|
||||
info "Package up to date in localrepo, skipping: ${pkg_name}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
||||
Executable
+184
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify that every quickshell pin we build against is current enough to
|
||||
# survive the next Arch Qt update.
|
||||
#
|
||||
# Why this exists: CI run 137 (2026-10-08) failed because end-4 pinned
|
||||
# quickshell to 41651d7 (Sep 25), which predates quickshell's Qt 6.12 fix
|
||||
# (5d5d498, Oct 3: "use MOC includes instead of opaque pointer definitions
|
||||
# - Fixes linking issues and Qt 6.12 compatibility"). Arch shipped
|
||||
# qt6 6.12.0 the next day and the pinned commit stopped compiling
|
||||
# ("Meta Types must be fully defined"). customize_airootfs.sh papers over
|
||||
# end-4's stale pin at build time; this script is the tripwire that tells
|
||||
# us when pins - ours OR end-4's - fall behind again BEFORE a build does.
|
||||
#
|
||||
# Checked pins:
|
||||
# 1. localrepo/end4-pkgbuilds/quickshell-git/PKGBUILD (our own pin)
|
||||
# 2. end-4/dots-hyprland sdata/dist-arch PKGBUILD (live from GitHub)
|
||||
#
|
||||
# Checks per pin:
|
||||
# - commit exists upstream
|
||||
# - includes the Qt 6.12 fix (5d5d498)
|
||||
# - not older than QUICKSHELL_PIN_MAX_AGE_DAYS (default 45)
|
||||
#
|
||||
# Exit 1 on any failure so CI (pin-check.yaml) goes red.
|
||||
#
|
||||
# Usage: ./localrepo/check-quickshell-pin.sh
|
||||
set -euo pipefail
|
||||
|
||||
QT612_FIX='5d5d49873fe8cf1f99ddfd5006ceb2057c5c9b13'
|
||||
QS_REPO='https://git.outfoxxed.me/quickshell/quickshell.git'
|
||||
END4_STALE_PIN='41651d7' # the pin customize_airootfs.sh overrides
|
||||
END4_PKGBUILD_URL='https://raw.githubusercontent.com/end-4/dots-hyprland/main/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD'
|
||||
MAX_AGE_DAYS="${QUICKSHELL_PIN_MAX_AGE_DAYS:-45}"
|
||||
|
||||
profile_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
LOCAL_PKGBUILD="${profile_dir}/localrepo/end4-pkgbuilds/quickshell-git/PKGBUILD"
|
||||
|
||||
FAILED=0
|
||||
|
||||
fail() {
|
||||
echo "❌ $1" >&2
|
||||
FAILED=1
|
||||
}
|
||||
|
||||
# ── collect pins ────────────────────────────────────────────────────────────
|
||||
|
||||
pin_of() { # <file-contents-stdin> -> first _commit='...' value
|
||||
sed -n "s/^_commit='\([0-9a-f]\{7,40\}\)'.*/\1/p" | head -n1
|
||||
}
|
||||
|
||||
if [[ ! -f "$LOCAL_PKGBUILD" ]]; then
|
||||
echo "❌ missing ${LOCAL_PKGBUILD}" >&2
|
||||
exit 1
|
||||
fi
|
||||
local_pin=$(pin_of < "$LOCAL_PKGBUILD")
|
||||
if [[ -z "$local_pin" ]]; then
|
||||
echo "❌ no _commit= found in ${LOCAL_PKGBUILD}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
end4_pin=''
|
||||
end4_pkgbuild=''
|
||||
for try in 1 2 3 4 5; do
|
||||
if end4_pkgbuild=$(curl -fsSL --max-time 30 "$END4_PKGBUILD_URL"); then
|
||||
end4_pin=$(printf '%s\n' "$end4_pkgbuild" | pin_of)
|
||||
break
|
||||
fi
|
||||
echo " ⏳ fetch of end-4 PKGBUILD failed (try $try/5), retrying in $(( try * 3 ))s..." >&2
|
||||
sleep $(( try * 3 ))
|
||||
done
|
||||
if [[ -z "$end4_pin" ]]; then
|
||||
fail "could not fetch end-4's quickshell PKGBUILD from GitHub — network or path change?"
|
||||
echo ""
|
||||
echo "Result: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── clone quickshell (blobless: commits+trees only, fast) ───────────────────
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
|
||||
cloned=0
|
||||
for try in 1 2 3; do
|
||||
if git clone --filter=blob:none --quiet "$QS_REPO" "$tmp/qs" 2>/dev/null; then
|
||||
cloned=1
|
||||
break
|
||||
fi
|
||||
rm -rf "$tmp/qs"
|
||||
echo " ⏳ clone of quickshell failed (try $try/3), retrying in $(( try * 5 ))s..." >&2
|
||||
sleep $(( try * 5 ))
|
||||
done
|
||||
if [[ "$cloned" -ne 1 ]]; then
|
||||
fail "could not clone ${QS_REPO} — network or repo moved?"
|
||||
echo ""
|
||||
echo "Result: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
QS="$tmp/qs"
|
||||
qs_head=$(git -C "$QS" rev-parse HEAD)
|
||||
qs_head_date=$(git -C "$QS" show -s --format=%cs HEAD)
|
||||
echo "quickshell upstream master: ${qs_head:0:12} (${qs_head_date})"
|
||||
echo ""
|
||||
|
||||
now=$(date +%s)
|
||||
|
||||
# <label> <pin> <mode>: mode "hard" fails on any problem; mode "soft" only
|
||||
# warns, for pins we don't control (end-4's) — UNLESS the problem is one the
|
||||
# customize_airootfs.sh override does not cover, which always fails hard
|
||||
# because it would break the next ISO build.
|
||||
check_pin() {
|
||||
local label=$1 pin=$2 mode=$3
|
||||
local ts age behind bad=0
|
||||
|
||||
if ! git -C "$QS" cat-file -e "${pin}^{commit}" 2>/dev/null; then
|
||||
fail "$label: pin '$pin' does not exist in quickshell upstream"
|
||||
return
|
||||
fi
|
||||
|
||||
local has_fix=0
|
||||
if git -C "$QS" merge-base --is-ancestor "$QT612_FIX" "$pin"; then
|
||||
has_fix=1
|
||||
fi
|
||||
|
||||
ts=$(git -C "$QS" show -s --format=%ct "$pin")
|
||||
age=$(( (now - ts) / 86400 ))
|
||||
behind=$(git -C "$QS" rev-list --count "$pin..HEAD")
|
||||
|
||||
if [[ "$mode" == "hard" ]]; then
|
||||
if [[ "$has_fix" -eq 0 ]]; then
|
||||
fail "$label: pin '$pin' PREDATES the Qt 6.12 fix (${QT612_FIX:0:12}) — will not compile against Qt >= 6.12"
|
||||
bad=1
|
||||
fi
|
||||
if (( age > MAX_AGE_DAYS )); then
|
||||
fail "$label: pin is $age days old (> ${MAX_AGE_DAYS}d), $behind commit(s) behind upstream master — bump it"
|
||||
bad=1
|
||||
fi
|
||||
if [[ "$bad" -eq 0 ]]; then
|
||||
echo " ✅ $label: pin ${pin:0:12} includes the Qt 6.12 fix, age ${age}d (${behind} commit(s) behind master)"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
# soft mode: our build-time override compensates for this pin, so drift is
|
||||
# a heads-up — it cannot break the ISO build on its own.
|
||||
if [[ "$has_fix" -eq 0 ]]; then
|
||||
echo " ⚠️ $label: pin ${pin:0:12} predates the Qt 6.12 fix — covered by the customize_airootfs.sh override, but end-4 should bump it"
|
||||
else
|
||||
echo " ✅ $label: pin ${pin:0:12} includes the Qt 6.12 fix"
|
||||
fi
|
||||
if (( age > MAX_AGE_DAYS )); then
|
||||
echo " ⚠️ $label: pin is $age days old (> ${MAX_AGE_DAYS}d), $behind commit(s) behind master — consider bumping (not enforced, we don't own this pin)"
|
||||
else
|
||||
echo " ✅ $label: pin age ${age}d (${behind} commit(s) behind master), limit ${MAX_AGE_DAYS}d"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── our pin ─────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "our pin (localrepo/end4-pkgbuilds):"
|
||||
check_pin "ours" "$local_pin" hard
|
||||
|
||||
# ── end-4's pin ─────────────────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
echo "end-4's pin (dots-hyprland sdata/dist-arch):"
|
||||
# end-4's pin is only safe if OUR override covers it: customize_airootfs.sh
|
||||
# rewrites exactly the 41651d7 pin. Any other Qt-unsafe end-4 pin sails
|
||||
# straight into the ISO build unpatched → hard failure.
|
||||
if [[ "$end4_pin" == "$END4_STALE_PIN"* ]]; then
|
||||
echo " ℹ️ end-4 still pins ${end4_pin:0:12} — customize_airootfs.sh override is active"
|
||||
check_pin "end-4" "$end4_pin" soft
|
||||
else
|
||||
check_pin "end-4" "$end4_pin" hard
|
||||
echo " ℹ️ end-4 has moved off ${END4_STALE_PIN} to ${end4_pin:0:12}"
|
||||
echo " → if it now passes, consider retiring the override guard in"
|
||||
echo " customize_airootfs.sh and syncing our own pin to match."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [[ "$FAILED" -ne 0 ]]; then
|
||||
echo "Result: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
echo "Result: OK — all quickshell pins are Qt 6.12-safe and within ${MAX_AGE_DAYS}d of upstream"
|
||||
@@ -18,6 +18,8 @@ depends=(
|
||||
makedepends=("git" "cmake")
|
||||
source=("git+${url}.git")
|
||||
sha256sums=("SKIP")
|
||||
# -O3 + LTO (CachyOS makepkg.conf) make GCC 16.2 ICE on gtkmm_main.cpp
|
||||
options=(!lto)
|
||||
|
||||
prepare() {
|
||||
cd $_pkgname
|
||||
@@ -26,6 +28,7 @@ prepare() {
|
||||
}
|
||||
|
||||
build() {
|
||||
export CFLAGS="${CFLAGS//-O3/-O2}" CXXFLAGS="${CXXFLAGS//-O3/-O2}"
|
||||
cd $_pkgname
|
||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=None
|
||||
cmake --build build
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
_commit='7511545ee20664e3b8b8d3322c0ffe7567c56f7a'
|
||||
_commit='11ca60be22b063478ed9586ca1d7f92f0f261caf'
|
||||
# Useful links:
|
||||
# https://git.outfoxxed.me/quickshell/quickshell/commits/branch/master
|
||||
# https://aur.archlinux.org/packages/quickshell-git
|
||||
@@ -8,7 +8,7 @@ _prefix='illogical-impulse'
|
||||
_pkgname=quickshell
|
||||
pkgname="$_prefix-$_pkgname-git"
|
||||
pkgver=0.1.0.r1
|
||||
pkgrel=8
|
||||
pkgrel=9
|
||||
pkgdesc="$_pkgname-git pinned commit and extra deps for $_prefix"
|
||||
arch=(x86_64 aarch64)
|
||||
url='https://git.outfoxxed.me/quickshell/quickshell'
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
-1
@@ -39,7 +39,8 @@ rm -f "${img_repo}"/*.pkg.tar.zst "${img_repo}/${repo_name}".db \
|
||||
"${img_repo}/${repo_name}".db.tar.gz "${img_repo}/${repo_name}".files \
|
||||
"${img_repo}/${repo_name}".files.tar.gz
|
||||
cp -f "${pkgs[@]}" "${img_repo}/"
|
||||
cp -fL "${repo_dir}/${repo_name}".db* "${repo_dir}/${repo_name}".files* "${img_repo}/"
|
||||
# explicit names: a .db* glob would also ship repo-add's *.tar.gz.old backups
|
||||
cp -fL "${repo_dir}/${repo_name}".{db,db.tar.gz,files,files.tar.gz} "${img_repo}/"
|
||||
echo "Medium copy ready: ${img_repo}"
|
||||
|
||||
new_names=()
|
||||
|
||||
+38
-23
@@ -3,8 +3,8 @@ alsa-utils
|
||||
amd-ucode
|
||||
ansible
|
||||
archinstall
|
||||
archlinux-keyring
|
||||
arch-install-scripts
|
||||
archlinux-keyring
|
||||
asciinema
|
||||
asciinema-agg
|
||||
ast-grep
|
||||
@@ -24,20 +24,21 @@ bolt
|
||||
brightnessctl
|
||||
brltty
|
||||
btop
|
||||
bullet
|
||||
btrfs-progs
|
||||
bullet
|
||||
bully
|
||||
cachyos-keyring
|
||||
cachyos-mirrorlist
|
||||
catppuccin-cursors-macchiato
|
||||
cava
|
||||
celt
|
||||
chaotic-keyring
|
||||
chaotic-mirrorlist
|
||||
cifs-utils
|
||||
clamav
|
||||
cliphist
|
||||
clonezilla
|
||||
cloud-init
|
||||
cliphist
|
||||
cmake
|
||||
cmatrix
|
||||
code
|
||||
@@ -50,13 +51,13 @@ curl
|
||||
darkhttpd
|
||||
davs2
|
||||
dconf-editor
|
||||
ddcutil
|
||||
ddrescue
|
||||
dhcpcd
|
||||
dialog
|
||||
diffutils
|
||||
dmidecode
|
||||
dmraid
|
||||
ddcutil
|
||||
dnsmasq
|
||||
dolphin-plugins
|
||||
dosfstools
|
||||
@@ -68,14 +69,12 @@ efibootmgr
|
||||
electron
|
||||
element-desktop
|
||||
espeakup
|
||||
eternalterminal
|
||||
ethtool
|
||||
exfatprogs
|
||||
f2fs-tools
|
||||
faac
|
||||
faad2
|
||||
fish
|
||||
flac
|
||||
fontconfig
|
||||
fastfetch
|
||||
fatresize
|
||||
fcitx5
|
||||
@@ -88,8 +87,11 @@ ffmpegthumbnailer
|
||||
ffmpegthumbs
|
||||
figlet
|
||||
firefox
|
||||
fish
|
||||
flac
|
||||
flatpak
|
||||
foliate
|
||||
fontconfig
|
||||
foot-terminfo
|
||||
foremost
|
||||
fortune-mod
|
||||
@@ -97,22 +99,23 @@ fprintd
|
||||
fsarchiver
|
||||
fuse-overlayfs
|
||||
fzf
|
||||
geoclue
|
||||
ghostty
|
||||
ghostty-terminfo
|
||||
git
|
||||
geoclue
|
||||
glib2-devel
|
||||
gnome-disk-utility
|
||||
gnome-font-viewer
|
||||
gnome-online-accounts
|
||||
gnome-power-manager
|
||||
go-yq
|
||||
gpart
|
||||
gparted
|
||||
go-yq
|
||||
gpm
|
||||
gptfdisk
|
||||
grml-zsh-config
|
||||
grub
|
||||
grub-customizer
|
||||
gst-plugins-base
|
||||
gst-plugins-ugly
|
||||
gst-plugin-va
|
||||
@@ -130,11 +133,12 @@ htop
|
||||
hyperv
|
||||
hypridle
|
||||
hyprlock
|
||||
hyprpolkitagent
|
||||
hyprpicker
|
||||
hyprpolkitagent
|
||||
hyprshot
|
||||
hyprsunset
|
||||
icu
|
||||
illogical-impulse-bibata-modern-classic-bin
|
||||
intel-ucode
|
||||
inxi
|
||||
irssi
|
||||
@@ -163,18 +167,18 @@ kwalletmanager
|
||||
lazygit
|
||||
ldns
|
||||
less
|
||||
lftp
|
||||
libass
|
||||
libdbusmenu-gtk3
|
||||
libdecor
|
||||
libevdev
|
||||
libportal
|
||||
libportal-gtk4
|
||||
libqalculate
|
||||
libpipewire
|
||||
lftp
|
||||
libfido2
|
||||
libfprint
|
||||
libisoburn
|
||||
libpipewire
|
||||
libportal
|
||||
libportal-gtk4
|
||||
libqalculate
|
||||
libtorrent
|
||||
libusb-compat
|
||||
linux-atm
|
||||
@@ -213,14 +217,14 @@ mplayer
|
||||
mpv-mpris
|
||||
mtools
|
||||
nano
|
||||
ncurses
|
||||
nbd
|
||||
ncurses
|
||||
ndisc6
|
||||
neofetch
|
||||
neovim
|
||||
net-tools
|
||||
network-manager-applet
|
||||
networkmanager
|
||||
network-manager-applet
|
||||
nfs-utils
|
||||
nikto
|
||||
nilfs-utils
|
||||
@@ -267,22 +271,23 @@ ppp
|
||||
pptpclient
|
||||
pv
|
||||
pwgen
|
||||
python-aiohttp
|
||||
python-distro
|
||||
python-hatchling
|
||||
python-installer
|
||||
python-packaging
|
||||
python-pip
|
||||
python-pyqt6
|
||||
python-pyquery
|
||||
python-ufonormalizer
|
||||
python-uv
|
||||
python-virtualenv
|
||||
python-aiohttp
|
||||
python-packaging
|
||||
qalculate-gtk
|
||||
qemu-full
|
||||
qemu-guest-agent
|
||||
qt5-quickcontrols2
|
||||
qt6ct
|
||||
qt6-5compat
|
||||
qt6ct
|
||||
qt6-imageformats
|
||||
qt6-multimedia
|
||||
qt6-positioning
|
||||
@@ -295,6 +300,7 @@ qt6-wayland
|
||||
rclone
|
||||
refind
|
||||
reflector
|
||||
rpi-imager-git
|
||||
rsync
|
||||
rxvt-unicode-terminfo
|
||||
samba
|
||||
@@ -312,12 +318,14 @@ shelly
|
||||
shelly-flatpak-backend
|
||||
shfmt
|
||||
smartmontools
|
||||
snapd
|
||||
sof-firmware
|
||||
sox
|
||||
songrec
|
||||
sox
|
||||
speech-dispatcher
|
||||
squashfs-tools
|
||||
sshfs
|
||||
ssh-import-id
|
||||
starship
|
||||
sudo
|
||||
swaync
|
||||
@@ -357,6 +365,7 @@ ttf-material-symbols-variable-git
|
||||
ttf-ms-fonts
|
||||
ttf-readex-pro
|
||||
ttf-twemoji
|
||||
ttf-victor-mono
|
||||
tty-clock
|
||||
tumbler
|
||||
udftools
|
||||
@@ -364,6 +373,7 @@ uget
|
||||
umockdev
|
||||
unrar
|
||||
upower
|
||||
upscayl-bin
|
||||
uriparser
|
||||
usbguard
|
||||
usb_modeswitch
|
||||
@@ -377,6 +387,10 @@ vim
|
||||
virt-manager
|
||||
virtualbox-guest-utils-nox
|
||||
vpnc
|
||||
vulkan-intel
|
||||
vulkan-nouveau
|
||||
vulkan-radeon
|
||||
wallust
|
||||
wayland-protocols
|
||||
wine
|
||||
winetricks
|
||||
@@ -384,15 +398,16 @@ wireless-regdb
|
||||
wireless_tools
|
||||
woeusb-ng
|
||||
wpa_supplicant
|
||||
wvdial
|
||||
wtype
|
||||
wvdial
|
||||
xarchiver
|
||||
xclip
|
||||
xdg-utils
|
||||
xdg-user-dirs
|
||||
xdg-utils
|
||||
xdotool
|
||||
xfsprogs
|
||||
xl2tpd
|
||||
xwaylandvideobridge
|
||||
yay
|
||||
ydotool
|
||||
yt-dlp
|
||||
|
||||
@@ -76,7 +76,6 @@ LocalFileSigLevel = Optional
|
||||
#Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[cachyos]
|
||||
SigLevel = Optional TrustAll
|
||||
Include = /etc/pacman.d/cachyos-mirrorlist
|
||||
|
||||
[core]
|
||||
@@ -98,7 +97,6 @@ Include = /etc/pacman.d/mirrorlist
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[chaotic-aur]
|
||||
SigLevel = Optional TrustAll
|
||||
Include = /etc/pacman.d/chaotic-mirrorlist
|
||||
|
||||
[local-aur]
|
||||
|
||||
+3
-2
@@ -27,8 +27,9 @@ file_permissions=(
|
||||
|
||||
# ── Build stamp (staged file, never committed) ────────────────────────────────
|
||||
# airootfs/root/.iso-build-stamp lands at /root/.iso-build-stamp on the ISO;
|
||||
# customize_airootfs.sh installs it as /etc/alvin-build-stamp, and alvin-install
|
||||
# appends it to the installed system's /etc/motd. Only stamp builds from a git
|
||||
# customize_airootfs.sh keeps it as /etc/alvin-build-stamp and appends it to
|
||||
# the live medium's /etc/motd (the installed system's motd is left alone).
|
||||
# Only stamp builds from a git
|
||||
# checkout or CI — a random source-tarball build would record a bogus commit.
|
||||
# Sourced by mkarchiso under `set -eu`, hence every expansion is defaulted.
|
||||
_stamp_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
Reference in New Issue
Block a user