build-end4-deps.sh builds in place, so pkg/, src/ and the VCS mirrors
under end4-pkgbuilds/ (incl. a built quickshell tree) ended up in git.
Ignore everything there except PKGBUILDs and hooks, plus *.old backups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `pacman -S` in the conflict check exits non-zero by design (a
conflict fails in prepare, a clean list fails at the disabled download),
and `OUT=$(...)` carries that status, so `bash -e` aborted the step
before the output was inspected: exit 1 with no message on every run.
Ignore the status and judge by the output, as intended.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The step ran `pacman -Sp`, which skips conflict checking entirely: it
happily prints URLs for eternalterminal + eternalterminal-client and
exits 0. It also skipped every localrepo package, so the conflict fixed
in f06bfd1 could never have been caught here.
Now the check resolves against a throwaway config that adds [local-aur]
(localrepo/), with a fresh dbpath/root so runner-installed packages
don't mask or fake conflicts, and runs a real `pacman -S`. Conflicts and
broken deps fail in "prepare", before any download; XferCommand is set
to /usr/bin/false after the sync so a clean list stops at the download
instead of fetching the whole ISO. Package availability comes from one
`-Slq` instead of ~400 `-Si` calls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f06bfd1 and a940d91 removed eternalterminal-client/-server,
illogical-impulse-quickshell-git, meshy-git and pacserve from
packages.x86_64, but their .pkg.tar.zst files stayed in localrepo/ and
in local-aur.db. update.sh appends every localrepo package name back to
the list, which would bring the eternalterminal conflict back, and CI
shipped the conflicting packages into the image's /opt/localrepo.
Remove the files and their repo DB entries, re-sort the vulkan-* lines
in packages.x86_64, and drop the names from README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- alvin-install: new sshd screen (default on) + install step. openssh is
guaranteed into the pacstrap list when requested, and the final banner
reports whether the enable actually succeeded (SSHD_APPLIED) instead of
what was selected. The prompt warns that password login uses the same
password as LUKS, and only mentions the GitHub key import when a
username was given.
- alvin-install: replay the `gsettings set` commands end-4 logged during
its setup run with a clean env and a throwaway session bus as the target
user, then read each key back in a second session to confirm it persisted
(gvariant_unescape normalizes both '...' and "..." GVariant output). The
venv check now walks the uv bin/python symlink chain, re-rooting
absolute hops under $TARGET, since that link dangles on the live medium.
- build: append the build stamp to the live /etc/motd (keeps the installed
system's motd untouched) and drop alvin-install's install_motd step.
- docs: installer sections in README/AGENTS.md, sshd notes, corrected line
counts.
Writing stock core/extra over the host /etc/pacman.conf raced with the
tests workflow, which appends [cachyos]/[chaotic-aur] to the same file —
runs 132 and 133 ran concurrently on the runner, so either job could
corrupt the other's config mid-pacman.
Use 'pacman --config $(mktemp)' with stock core/extra instead: same
DNS-lookup reduction (only core/extra sync, no cachyos/chaotic), zero
writes to shared state. Verified on the runner: exit 0, only core/extra
synced, host /etc/pacman.conf mtime unchanged.
Run 131 failed at 'pacman -Syu archiso jq' because the gateway
(192.168.1.1) intermittently drops UDP/53: cachyos.db and chaotic-aur.db
lookups hit libalpm's 10s resolve timeout while core/extra survived on
resolved's cache.
- build-iso: reset the host /etc/pacman.conf to stock core/extra first
(tests.yaml leaves [cachyos]/[chaotic-aur] behind, and mkarchiso reads
the profile's pacman.conf anyway), pre-warm mirror hostnames in the
resolver cache, then retry pacman -Syu 5x with backoff.
- tests: wrap all three pacman -Syu calls in the same retry loop.
DNS-side redundancy was added on the runner separately (networkd drop-in
adds 1.1.1.1/8.8.8.8 next to the gateway).
The chroot's /dev only gains fd/stdin/stdout/stderr symlinks at boot, and
container executors often lack them, which breaks mkinitcpio's preset step
(pipes through /dev/stdin) and bash process substitution
("/dev/fd/63: No such file or directory").
- build-iso workflow: create the links in the executor's /dev, then mount a
fresh devtmpfs and create them there too so the chroot tree is covered
whether the executor's /dev is devtmpfs or a plain tmpfs
- customize_airootfs.sh: self-heal the same links inside the chroot
screen_git now prompts GitHub username before git name/email, and the
screen description plus installation summary list SSH before git to
match the new prompt order. Behavior unchanged - prompts are
independent and all assignment sites are read after the screen returns.
CI package check failed on main (400/402):
- syncthingtray-qt6 no longer exists in the AUR (RPC returns nothing);
the qt6 build is now the official 'syncthingtray' package in extra/
cachyos - rename it in packages.x86_64 and drop the dead
AUR_MISSING entry from build-end4-deps.sh
- neofetch left the distro repos (only chaotic-neofetch-git remains);
build the AUR package locally (7.1.0-2, PGP-verified against Dylan
Araps' key) and commit it to localrepo/ with a reindexed local-aur
db so both the CI check (file glob) and pacstrap ([local-aur]) work
- un-indent the package lists in build-end4-deps.sh: CI accepts
repo-less packages via 'grep -qxF <name>' (exact whole-line match),
which could never match indented names
Verified locally with an exact replica of the CI check: 402/402.
- profiledef.sh stages airootfs/root/.iso-build-stamp (git/CI gated, falls
back to 'commit unknown'); customize_airootfs.sh installs it as
/etc/alvin-build-stamp; install_motd appends it to the target /etc/motd
- alvin-install: skippable git/GitHub screens with ssh-import-id import
(yay build + python-distro, curl .keys fallback), LUKS Mode A (systemd
sd-encrypt + rd.luks.name) vs Mode B (unl0kr + cryptdevice), TPM2
enrollment via $PASSWORD with rd.luks.options activation, unl0kr
build/verify with Mode-A fallback, login manager none/greetd/sddm/gdm
(enable DM before disabling getty@tty1), autologin per DM (forced off
when TPM enrolled), build-stamp motd; includes the existing
GRUB_DISABLE_BOOTNEXT grub tweak
- review fixes: greetd autologin TOML quoting, .ssh chowned before
ssh-import-id, builtin-aware initramfs module verification across all
installed kernels, curl exit-code split (fetch failure vs no keys),
plain Hyprland on every login path
- add curl to packages.x86_64; document stamp flow and installer in
AGENTS.md/README.md
Two low-severity review findings on 8501a60:
- owner="$(id -u):$(id -g)" as two substitutions only propagates the
last status, so a lone id -u failure would build ':1000' and abort at
the chown with "invalid owner" under the wrong line. Run both ids in
a single arch-chroot sh -c chained with && and join with paste -sd:;
pipefail makes any failure abort at the owner= line. Verified both
paths: existing user yields 1000:1000, missing user trips the ERR
trap before owner is used.
- the ydotool symlink mkdir/ln wrote stderr to the terminal while the
failure warn pointed at $LOG, which never recorded it; redirect both
into the log, matching the bluetooth block.
The end-4 step's chowns ran on the live medium, whose /etc/passwd has
no $USERNAME (the user exists only inside /mnt), so 'chown -R
alvin:alvin' failed with "invalid user" and the ERR trap aborted the
install at line 543. Resolve uid/gid once via arch-chroot id and chown
by number; the three remaining name-based chowns (fork/fish/hypr
restores) would have hit the same wall later.
Replace those three mid-function chowns with one catch-all over the
target home after the last root-side write: sed -i on the presets
rewrites through a temp file, which leaves them root-owned with no
chown after it.
systemctl --user enable ydotool.service could never work inside the
chroot (no /run/user/UID/bus exists before boot; it only ever warned
with "Failed to connect to user scope bus", so ydotool never
autostarted). Write the symlink enable would write:
~/.config/systemd/user/default.target.wants/ydotool.service ->
/usr/lib/systemd/user/ydotool.service.
`curl -f` swallowed Gitea's error response, so the 3-attempt upload
failure on the 6330 MiB ISO reported nothing diagnosable. Capture the
status code via -w, print up to 2 KB of the response body for both
HTTP-level and transport-level failures, and clear upload.json at the
start of each attempt so a stale body cannot be misreported.
end-4's ./setup sudo keepalive orphans a `sleep 60` child as ii-builder;
userdel then exits 8 and aborts the ISO build (CI exit 8).
Sweep uid-matching processes inside the build chroot before userdel,
mirroring shadow's user_busy_processes() checks (real/effective/saved
uid + root device/inode). Because arch-chroot mounts proc before
`unshare --fork --pid`, /proc entry numbers are outer-namespace pids:
signal the last NSpid field instead, require matching NSpid depth, and
surface kill errors instead of swallowing them. userdel keeps its stderr
and, on final failure, dumps the leftover process list before aborting.
- customize_airootfs.sh stages dots-hyprland at /opt, runs ./setup
install-deps as a throwaway builder, harvests the built packages into
/opt/localrepo so pacstrap resolves them offline
- image ships its own [local-aur] (file:///opt/localrepo); CI and
localrepo/update.sh keep that copy in sync; .gitignore covers work/,
out/ and airootfs/opt/localrepo/
- alvin-install runs ./setup install --skip-alldeps on the target
- clone pctrade/end4-pC into /etc/skel/.config/quickshell, patch qsConfig
ii -> end4-pC in the staged variables.lua (guarded + idempotent), and
restore the fork after setup rsync --delete's ~/.config/quickshell
- ship user presets in skel, point fish `q` alias at end4-pC
- AGENTS.md: document the fourth package source and new gotchas
- Export SOURCE_DATE_EPOCH before mkarchiso so label, volume UUID,
file mtimes and ext4 hash seed trace to one timestamp.
- Post-build step: assert blkid UUID of the ISO matches every
/boot/<uuid>.uuid stem and archisosearchuuid= reference inside
shipped boot configs, and that no %ARCHISO% placeholder remains.
- After upload: re-hash local ISOs, size-check API assets, download
each back from the internal origin (bypasses traefik/Anubis) with
percent-encoded filenames (iso_name contains a space), compare
SHA-256. Definitive corruption (missing/size/sha mismatch) deletes
the release; transport/API errors fail without deleting.
pacstrap failed at line 382 because pkglist lines from pacman -Q are
'name version' and were passed whole as pacman targets (~400 'target
not found'). Parse only the first field, pre-filter against pacman -Slq
so packages missing from the live repos (local-aur) are skipped with a
warning, and fall back to an unfiltered list if pacman -Syy fails.
Keymap screen now offers a US-layout confirm before the gum filter.
- New gum-based installer script (alvin-install) with LUKS encryption,
nmtui networking, disk selector, user/git config, and CachyOS repo setup
- Replace NetworkManager full unit file with symlink for consistency
- Add alvin-install reference to MOTD
- Add file_permissions entry in profiledef.sh
- Fix localrepo path case in pacman.conf
Boot configs referenced stock vmlinuz-linux/initramfs-linux.img but
only linux-cachyos is installed. This caused boot to fall through
to memtest86+ since the kernel file was not found.
The GITEA_TOKEN lacks 'lfs' scope, causing the LFS batch API to reject
uploads. Upload .zst files directly as release assets via the Gitea API
instead. This eliminates git-lfs, the separate releases repo, and all
LFS-related plumbing.
- Add CI step to create /dev/stdin symlinks before ISO build
(Docker/container environments may lack these, causing mkinitcpio to fail)
- Remove stock linux kernel from packages.x86_64 (linux-cachyos is the
intended kernel; dual-kernel causes boot confusion and doubles build time)
Closes #X
Create a matching git tag + release in alvinlollo/AlvinArch-releases next to
the main repo release, seed a short README there pointing back to
AlvinArch (workflow status badges on top), and extend release pruning to
the releases repo so both stay capped at 3.
Release assets can no longer be attached directly (Gitea 500 on multi-GB
uploads). Compress each ISO with zstd, push the .zst into
alvinlollo/AlvinArch-releases (releases/<tag>/ on main) via Git LFS, verify
the LFS object server-side by OID, and create the release with a download
link plus SHA-256 checksums instead of a binary attachment.
These files exist in the airootfs overlay but are owned by packages
in packages.x86_64, causing 'exists in filesystem' errors during
mkarchiso pacman install:
- usr/lib/os-release (filesystem)
- usr/share/pacman/keyrings/cachyos-* (cachyos-keyring)
- etc/clamav/certs/clamav.crt (clamav)
- etc/skel/.zshrc (grml-zsh-config)
build-iso:
- Remove -c flag (it takes a pacman.conf path, not a clean flag)
- Use absolute paths for mkarchiso with -- separator
- Copy local-aur.files* alongside local-aur.db*
tests:
- Fix word splitting: use 'while IFS= read -r' instead of
'for f in ' for shell and YAML file loops
- Fix YAML find filter to use -not -path like shell find
Use -- to separate flags from profile path, preventing mkarchiso
from misinterpreting the -w argument as the profile directory.
Also make rm -rf fail-safe with || true.