mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-12-13 12:44:38 +00:00
Compare commits
6 Commits
feature/mu
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 57ec936d30 | |||
| f143ce258c | |||
| 060ae45c7d | |||
| a3ba40edb6 | |||
| f9825ac4fc | |||
| 9d66910120 |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,3 +1,13 @@
|
|||||||
|
## [0.2.0] - 2025-12-10
|
||||||
|
|
||||||
|
* Added full Nix installer integration with dynamic upstream SHA256 verification, OS-specific installation paths, template-driven configuration, and updated pkgmgr integration.
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.1] - 2025-12-10
|
||||||
|
|
||||||
|
* PKGMGR will now be pulled again
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0] - 2025-12-09
|
## [0.1.0] - 2025-12-09
|
||||||
|
|
||||||
* Added Nix support role
|
* Added Nix support role
|
||||||
|
|||||||
154
Dockerfile
154
Dockerfile
@@ -1,132 +1,60 @@
|
|||||||
# ------------------------------------------------------------
|
FROM archlinux:latest
|
||||||
# Infinito dev container (multi-distro)
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
ARG BASE_IMAGE=archlinux:latest
|
|
||||||
FROM ${BASE_IMAGE}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# 1) Pakete inkl. docker (damit docker CLI im Container vorhanden ist)
|
||||||
# Base dependencies per distro
|
RUN pacman -Syu --noconfirm \
|
||||||
# - git, python, venv tooling
|
base-devel \
|
||||||
# - docker CLI (best-effort)
|
git \
|
||||||
# - rsync, build tools, CA certificates
|
python \
|
||||||
# ------------------------------------------------------------
|
python-pip \
|
||||||
RUN set -e; \
|
python-setuptools \
|
||||||
if [ -f /etc/os-release ]; then \
|
alsa-lib \
|
||||||
. /etc/os-release; \
|
go \
|
||||||
else \
|
rsync \
|
||||||
echo "ERROR: /etc/os-release not found, cannot detect distro."; \
|
docker \
|
||||||
exit 1; \
|
&& pacman -Scc --noconfirm
|
||||||
fi; \
|
|
||||||
echo "[infinito] Detected base distro: ${ID:-unknown}"; \
|
|
||||||
case "${ID}" in \
|
|
||||||
arch) \
|
|
||||||
pacman -Syu --noconfirm \
|
|
||||||
base-devel \
|
|
||||||
git \
|
|
||||||
python \
|
|
||||||
python-pip \
|
|
||||||
python-setuptools \
|
|
||||||
rsync \
|
|
||||||
alsa-lib \
|
|
||||||
go \
|
|
||||||
docker \
|
|
||||||
curl \
|
|
||||||
ca-certificates; \
|
|
||||||
pacman -Scc --noconfirm; \
|
|
||||||
# Ensure python3 exists (Arch only ships 'python' by default) \
|
|
||||||
if [ ! -x /usr/bin/python3 ]; then \
|
|
||||||
ln -sf /usr/bin/python /usr/bin/python3; \
|
|
||||||
fi; \
|
|
||||||
# Stub systemctl and yay to avoid side effects in containers \
|
|
||||||
printf '#!/bin/sh\nexit 0\n' > /usr/bin/systemctl; \
|
|
||||||
chmod +x /usr/bin/systemctl; \
|
|
||||||
printf '#!/bin/sh\nexit 0\n' > /usr/bin/yay; \
|
|
||||||
chmod +x /usr/bin/yay; \
|
|
||||||
;; \
|
|
||||||
debian|ubuntu) \
|
|
||||||
apt-get update; \
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
||||||
build-essential \
|
|
||||||
git \
|
|
||||||
python3 \
|
|
||||||
python3-venv \
|
|
||||||
python3-pip \
|
|
||||||
python3-setuptools \
|
|
||||||
rsync \
|
|
||||||
libasound2 \
|
|
||||||
docker.io \
|
|
||||||
curl \
|
|
||||||
ca-certificates; \
|
|
||||||
rm -rf /var/lib/apt/lists/*; \
|
|
||||||
;; \
|
|
||||||
fedora|rhel|centos) \
|
|
||||||
dnf -y update; \
|
|
||||||
dnf -y install \
|
|
||||||
git \
|
|
||||||
python3 \
|
|
||||||
python3-pip \
|
|
||||||
python3-setuptools \
|
|
||||||
make \
|
|
||||||
gcc \
|
|
||||||
rsync \
|
|
||||||
alsa-lib \
|
|
||||||
docker \
|
|
||||||
curl \
|
|
||||||
ca-certificates \
|
|
||||||
xz; \
|
|
||||||
dnf clean all; \
|
|
||||||
;; \
|
|
||||||
*) \
|
|
||||||
echo "ERROR: Unsupported base distro '${ID}'."; \
|
|
||||||
exit 1; \
|
|
||||||
;; \
|
|
||||||
esac
|
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# 2) systemctl & yay stubben
|
||||||
# pkgmgr via Python venv (distro-agnostic)
|
RUN printf '#!/bin/sh\nexit 0\n' > /usr/bin/systemctl \
|
||||||
# ------------------------------------------------------------
|
&& chmod +x /usr/bin/systemctl \
|
||||||
|
&& printf '#!/bin/sh\nexit 0\n' > /usr/bin/yay \
|
||||||
|
&& chmod +x /usr/bin/yay
|
||||||
|
|
||||||
|
# 3) python-simpleaudio aus AUR
|
||||||
|
RUN useradd -m aur_builder \
|
||||||
|
&& su aur_builder -c "git clone https://aur.archlinux.org/python-simpleaudio.git /home/aur_builder/psa && \
|
||||||
|
cd /home/aur_builder/psa && \
|
||||||
|
makepkg --noconfirm --skippgpcheck" \
|
||||||
|
&& pacman -U --noconfirm /home/aur_builder/psa/*.pkg.tar.zst \
|
||||||
|
&& rm -rf /home/aur_builder/psa
|
||||||
|
|
||||||
|
# 4) pkgmgr + venv
|
||||||
ENV PKGMGR_REPO=/opt/package-manager \
|
ENV PKGMGR_REPO=/opt/package-manager \
|
||||||
PKGMGR_VENV=/root/.venvs/pkgmgr
|
PKGMGR_VENV=/root/.venvs/pkgmgr
|
||||||
|
|
||||||
RUN git clone https://github.com/kevinveenbirkenbach/package-manager.git "$PKGMGR_REPO" \
|
RUN git clone https://github.com/kevinveenbirkenbach/package-manager.git $PKGMGR_REPO \
|
||||||
&& python3 -m venv "$PKGMGR_VENV" \
|
&& python -m venv $PKGMGR_VENV \
|
||||||
&& "$PKGMGR_VENV/bin/pip" install --upgrade pip \
|
&& $PKGMGR_VENV/bin/pip install --upgrade pip \
|
||||||
&& "$PKGMGR_VENV/bin/pip" install --no-cache-dir \
|
&& $PKGMGR_VENV/bin/pip install --no-cache-dir -r $PKGMGR_REPO/requirements.txt ansible \
|
||||||
-r "$PKGMGR_REPO/requirements.txt" \
|
|
||||||
ansible \
|
|
||||||
simpleaudio \
|
|
||||||
&& printf '#!/bin/sh\n. %s/bin/activate\nexec python %s/main.py "$@"\n' \
|
&& printf '#!/bin/sh\n. %s/bin/activate\nexec python %s/main.py "$@"\n' \
|
||||||
"$PKGMGR_VENV" "$PKGMGR_REPO" > /usr/local/bin/pkgmgr \
|
"$PKGMGR_VENV" "$PKGMGR_REPO" > /usr/local/bin/pkgmgr \
|
||||||
&& chmod +x /usr/local/bin/pkgmgr
|
&& chmod +x /usr/local/bin/pkgmgr
|
||||||
|
|
||||||
ENV PATH="$PKGMGR_VENV/bin:/root/.local/bin:${PATH}"
|
ENV PATH="$PKGMGR_VENV/bin:/root/.local/bin:${PATH}"
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# 6) Infinito.Nexus Quelle rein
|
||||||
# Copy local Infinito source into the image
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
COPY . /opt/infinito-src
|
COPY . /opt/infinito-src
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# 7) Infinito via pkgmgr (shallow)
|
||||||
# Install Infinito via pkgmgr (shallow clone)
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
RUN pkgmgr install infinito --clone-mode shallow
|
RUN pkgmgr install infinito --clone-mode shallow
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# 8) Override mit lokaler Quelle
|
||||||
# Override installed Infinito with local source
|
RUN INFINITO_PATH=$(pkgmgr path infinito) && \
|
||||||
# (keeps pkgmgr metadata, but code comes from /opt/infinito-src)
|
rm -rf "$INFINITO_PATH"/* && \
|
||||||
# ------------------------------------------------------------
|
rsync -a --delete --exclude='.git' /opt/infinito-src/ "$INFINITO_PATH"/
|
||||||
RUN INFINITO_PATH="$(pkgmgr path infinito)" && \
|
|
||||||
rm -rf "${INFINITO_PATH:?}"/* && \
|
|
||||||
rsync -a --delete --exclude='.git' /opt/infinito-src/ "${INFINITO_PATH}/"
|
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# 9) Symlink
|
||||||
# Symlink infinito CLI into PATH
|
RUN INFINITO_PATH=$(pkgmgr path infinito) && \
|
||||||
# ------------------------------------------------------------
|
ln -sf "$INFINITO_PATH"/main.py /usr/local/bin/infinito && \
|
||||||
RUN INFINITO_PATH="$(pkgmgr path infinito)" && \
|
|
||||||
ln -sf "${INFINITO_PATH}/main.py" /usr/local/bin/infinito && \
|
|
||||||
chmod +x /usr/local/bin/infinito
|
chmod +x /usr/local/bin/infinito
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
# Default command: show help and keep container running
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
CMD sh -c "infinito --help && exec tail -f /dev/null"
|
CMD sh -c "infinito --help && exec tail -f /dev/null"
|
||||||
|
|||||||
99
Makefile
99
Makefile
@@ -1,24 +1,3 @@
|
|||||||
# ------------------------------------------------------------
|
|
||||||
# Multi-distro Docker build configuration (similar to pkgmgr)
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
DISTROS := arch debian ubuntu fedora centos
|
|
||||||
BASE_IMAGE_ARCH := archlinux:latest
|
|
||||||
BASE_IMAGE_DEBIAN := debian:stable-slim
|
|
||||||
BASE_IMAGE_UBUNTU := ubuntu:latest
|
|
||||||
BASE_IMAGE_FEDORA := fedora:latest
|
|
||||||
BASE_IMAGE_CENTOS := quay.io/centos/centos:stream9
|
|
||||||
|
|
||||||
# Make them available to scripts (if you later add resolve-base-image.sh, etc.)
|
|
||||||
export DISTROS
|
|
||||||
export BASE_IMAGE_ARCH
|
|
||||||
export BASE_IMAGE_DEBIAN
|
|
||||||
export BASE_IMAGE_UBUNTU
|
|
||||||
export BASE_IMAGE_FEDORA
|
|
||||||
export BASE_IMAGE_CENTOS
|
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
# Infinito roles/config generation
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
ROLES_DIR := ./roles
|
ROLES_DIR := ./roles
|
||||||
APPLICATIONS_OUT := ./group_vars/all/04_applications.yml
|
APPLICATIONS_OUT := ./group_vars/all/04_applications.yml
|
||||||
APPLICATIONS_SCRIPT := ./cli/build/defaults/applications.py
|
APPLICATIONS_SCRIPT := ./cli/build/defaults/applications.py
|
||||||
@@ -40,36 +19,31 @@ RESERVED_USERNAMES := $(shell \
|
|||||||
| paste -sd, - \
|
| paste -sd, - \
|
||||||
)
|
)
|
||||||
|
|
||||||
.PHONY: build install test clean clean-keep-logs list tree mig dockerignore \
|
.PHONY: build install test
|
||||||
messy-build messy-test \
|
|
||||||
docker-build docker-build-no-cache
|
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
# Core project targets
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
clean-keep-logs:
|
clean-keep-logs:
|
||||||
@echo "🧹 Cleaning ignored files but keeping logs/…"
|
@echo "🧹 Cleaning ignored files but keeping logs/…"
|
||||||
git clean -fdX -- ':!logs' ':!logs/**'
|
git clean -fdX -- ':!logs' ':!logs/**'
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "🧹 Removing ignored git files…"
|
@echo "Removing ignored git files"
|
||||||
git clean -fdX
|
git clean -fdX
|
||||||
|
|
||||||
list:
|
list:
|
||||||
@echo "📦 Generating the roles list…"
|
@echo Generating the roles list
|
||||||
python3 main.py build roles_list
|
python3 main.py build roles_list
|
||||||
|
|
||||||
tree:
|
tree:
|
||||||
@echo "🌳 Generating roles tree…"
|
@echo Generating Tree
|
||||||
python3 main.py build tree -D 2 --no-signal
|
python3 main.py build tree -D 2 --no-signal
|
||||||
|
|
||||||
mig: list tree
|
mig: list tree
|
||||||
@echo "🔗 Creating meta data for meta infinity graph…"
|
@echo Creating meta data for meta infinity graph
|
||||||
|
|
||||||
dockerignore:
|
dockerignore:
|
||||||
@echo "📝 Creating .dockerignore from .gitignore…"
|
@echo Create dockerignore
|
||||||
cat .gitignore > .dockerignore
|
cat .gitignore > .dockerignore
|
||||||
echo ".git" >> .dockerignore
|
echo ".git" >> .dockerignore
|
||||||
|
|
||||||
messy-build: dockerignore
|
messy-build: dockerignore
|
||||||
@echo "🔧 Generating users defaults → $(USERS_OUT)…"
|
@echo "🔧 Generating users defaults → $(USERS_OUT)…"
|
||||||
@@ -95,7 +69,7 @@ messy-build: dockerignore
|
|||||||
echo " ✅ $$out"; \
|
echo " ✅ $$out"; \
|
||||||
)
|
)
|
||||||
|
|
||||||
messy-test:
|
messy-test:
|
||||||
@echo "🧪 Running Python tests…"
|
@echo "🧪 Running Python tests…"
|
||||||
PYTHONPATH=. python -m unittest discover -s tests
|
PYTHONPATH=. python -m unittest discover -s tests
|
||||||
@echo "📑 Checking Ansible syntax…"
|
@echo "📑 Checking Ansible syntax…"
|
||||||
@@ -105,60 +79,7 @@ install: build
|
|||||||
@echo "⚙️ Install complete."
|
@echo "⚙️ Install complete."
|
||||||
|
|
||||||
build: clean messy-build
|
build: clean messy-build
|
||||||
@echo "✅ Full build (with cleanup) finished."
|
@echo "Full build with cleanup before was executed."
|
||||||
|
|
||||||
test: build messy-test
|
test: build messy-test
|
||||||
@echo "✅ Full test (with build) finished."
|
@echo "Full test with build before was executed."
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
# Docker: multi-distro dev containers for Infinito
|
|
||||||
# Uses the multi-distro Dockerfile with ARG BASE_IMAGE
|
|
||||||
# ------------------------------------------------------------
|
|
||||||
|
|
||||||
# Helper to map distro → BASE_IMAGE_* variable
|
|
||||||
define _infinito_base_image
|
|
||||||
$(if $(filter $(1),arch),$(BASE_IMAGE_ARCH),\
|
|
||||||
$(if $(filter $(1),debian),$(BASE_IMAGE_DEBIAN),\
|
|
||||||
$(if $(filter $(1),ubuntu),$(BASE_IMAGE_UBUNTU),\
|
|
||||||
$(if $(filter $(1),fedora),$(BASE_IMAGE_FEDORA),\
|
|
||||||
$(if $(filter $(1),centos),$(BASE_IMAGE_CENTOS),)))))
|
|
||||||
endef
|
|
||||||
|
|
||||||
docker-build:
|
|
||||||
@echo "============================================================"
|
|
||||||
@echo ">>> Building Infinito dev containers for: $(DISTROS)"
|
|
||||||
@echo "============================================================"
|
|
||||||
@for distro in $(DISTROS); do \
|
|
||||||
base_image="$(call _infinito_base_image,$$distro)"; \
|
|
||||||
image_name="infinito-dev-$$distro"; \
|
|
||||||
echo; \
|
|
||||||
echo "------------------------------------------------------------"; \
|
|
||||||
echo ">>> Building $$image_name (BASE_IMAGE=$$base_image)…"; \
|
|
||||||
echo "------------------------------------------------------------"; \
|
|
||||||
docker build \
|
|
||||||
--build-arg BASE_IMAGE="$$base_image" \
|
|
||||||
-t "$$image_name" \
|
|
||||||
. || exit $$?; \
|
|
||||||
done
|
|
||||||
@echo
|
|
||||||
@echo "✅ All Infinito dev images built."
|
|
||||||
|
|
||||||
docker-build-no-cache:
|
|
||||||
@echo "============================================================"
|
|
||||||
@echo ">>> Building Infinito dev containers (NO CACHE) for: $(DISTROS)"
|
|
||||||
@echo "============================================================"
|
|
||||||
@for distro in $(DISTROS); do \
|
|
||||||
base_image="$(call _infinito_base_image,$$distro)"; \
|
|
||||||
image_name="infinito-dev-$$distro"; \
|
|
||||||
echo; \
|
|
||||||
echo "------------------------------------------------------------"; \
|
|
||||||
echo ">>> Building $$image_name with NO CACHE (BASE_IMAGE=$$base_image)…"; \
|
|
||||||
echo "------------------------------------------------------------"; \
|
|
||||||
docker build \
|
|
||||||
--no-cache \
|
|
||||||
--build-arg BASE_IMAGE="$$base_image" \
|
|
||||||
-t "$$image_name" \
|
|
||||||
. || exit $$?; \
|
|
||||||
done
|
|
||||||
@echo
|
|
||||||
@echo "✅ All Infinito dev images built (no cache)."
|
|
||||||
|
|||||||
2
roles/dev-nix/TODO.md
Normal file
2
roles/dev-nix/TODO.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# to-dos
|
||||||
|
- Implement better hash validation for security
|
||||||
@@ -1,14 +1,22 @@
|
|||||||
---
|
---
|
||||||
# Path to the installer script inside this role
|
# Nix version to install via official installer
|
||||||
dev_nix_installer_source: "nix-install.sh"
|
dev_nix_installer_version: "2.32.4"
|
||||||
|
|
||||||
# Path where the installer will be copied on the target host
|
# Base URL for Nix releases
|
||||||
|
dev_nix_installer_base_url: "https://releases.nixos.org/nix"
|
||||||
|
|
||||||
|
# Full URL to the installer script (can be overridden if needed)
|
||||||
|
dev_nix_installer_url: >-
|
||||||
|
{{ dev_nix_installer_base_url }}/nix-{{ dev_nix_installer_version }}/install
|
||||||
|
|
||||||
|
# Full URL to the SHA256 checksum file
|
||||||
|
dev_nix_installer_sha256_url: "{{ dev_nix_installer_url }}.sha256"
|
||||||
|
|
||||||
|
# Path where the installer will be downloaded on the target host
|
||||||
dev_nix_installer_dest: "/usr/local/share/nix-install.sh"
|
dev_nix_installer_dest: "/usr/local/share/nix-install.sh"
|
||||||
|
|
||||||
# Expected SHA256 of the installer file.
|
# Will be filled at runtime from dev_nix_installer_sha256_url
|
||||||
# You MUST set this to the actual hash of files/nix-install.sh, e.g.:
|
dev_nix_installer_sha256: ""
|
||||||
# sha256sum roles/dev-nix/files/nix-install.sh
|
|
||||||
dev_nix_installer_sha256: "CHANGE_ME_SHA256_OF_INSTALLER"
|
|
||||||
|
|
||||||
# Whether to drop a small shell snippet into /etc/profile.d to ensure
|
# Whether to drop a small shell snippet into /etc/profile.d to ensure
|
||||||
# Nix environment is available for login shells.
|
# Nix environment is available for login shells.
|
||||||
@@ -16,3 +24,11 @@ dev_nix_enable_shell_snippet: false
|
|||||||
|
|
||||||
# Path of the profile.d snippet
|
# Path of the profile.d snippet
|
||||||
dev_nix_shell_snippet_path: "/etc/profile.d/nix.sh"
|
dev_nix_shell_snippet_path: "/etc/profile.d/nix.sh"
|
||||||
|
|
||||||
|
# Enable experimental features such as nix-command and flakes
|
||||||
|
dev_nix_enable_experimental_features: true
|
||||||
|
|
||||||
|
# List of experimental features to enable when dev_nix_enable_experimental_features is true
|
||||||
|
dev_nix_experimental_features:
|
||||||
|
- nix-command
|
||||||
|
- flakes
|
||||||
|
|||||||
49
roles/dev-nix/tasks/01_core.yml
Normal file
49
roles/dev-nix/tasks/01_core.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
# Install Nix differently depending on the target platform:
|
||||||
|
# - Arch-based systems: install via package manager
|
||||||
|
# - Non-Arch systems: use the official installer with SHA256 verification
|
||||||
|
|
||||||
|
# 1) Arch-based systems: just install the distro package
|
||||||
|
- name: Install Nix via package manager on Arch-based systems
|
||||||
|
community.general.pacman:
|
||||||
|
name: nix
|
||||||
|
state: present
|
||||||
|
become: true
|
||||||
|
when: ansible_facts.os_family == "Archlinux"
|
||||||
|
|
||||||
|
# 2) Non-Arch systems: delegate installer logic to a separate task file
|
||||||
|
- name: Include non-Arch installer logic
|
||||||
|
ansible.builtin.include_tasks: 02_non_arch_installer.yml
|
||||||
|
when: ansible_facts.os_family != "Archlinux"
|
||||||
|
|
||||||
|
# 3) Configure Nix experimental features (common for all platforms)
|
||||||
|
- name: Ensure Nix config directory exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/nix
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
when: dev_nix_enable_experimental_features | bool
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy Nix configuration (nix.conf)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "nix.conf.j2"
|
||||||
|
dest: "/etc/nix/nix.conf"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
# 4) Optionally drop shell snippet for Nix
|
||||||
|
- name: Optionally drop shell snippet for Nix
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ dev_nix_shell_snippet_path }}"
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
# Added by dev-nix Ansible role
|
||||||
|
if [ -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
|
||||||
|
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||||
|
fi
|
||||||
|
when: dev_nix_enable_shell_snippet | bool
|
||||||
|
become: true
|
||||||
|
|
||||||
|
# 5) Mark this role as "run once" in your global once-flag system
|
||||||
|
- include_tasks: utils/once/flag.yml
|
||||||
37
roles/dev-nix/tasks/02_non_arch_installer.yml
Normal file
37
roles/dev-nix/tasks/02_non_arch_installer.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
# Non-Arch installer logic:
|
||||||
|
# Download the official Nix installer and its SHA256 from releases.nixos.org
|
||||||
|
# and run the daemon (multi-user) installer.
|
||||||
|
|
||||||
|
# 1) Fetch the official SHA256 from releases.nixos.org on the control node
|
||||||
|
- name: Fetch official Nix installer SHA256
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: "{{ dev_nix_installer_sha256_url }}"
|
||||||
|
return_content: true
|
||||||
|
register: dev_nix_official_sha_response
|
||||||
|
delegate_to: localhost
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
- name: Set expected installer checksum from official SHA256
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
dev_nix_installer_sha256: >-
|
||||||
|
{{ dev_nix_official_sha_response.content.split()[0] | trim }}
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
# 2) Download installer script on the target and verify via checksum
|
||||||
|
- name: Download Nix installer script from official releases
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "{{ dev_nix_installer_url }}"
|
||||||
|
dest: "{{ dev_nix_installer_dest }}"
|
||||||
|
mode: "0755"
|
||||||
|
# get_url will verify the checksum and fail if it does not match
|
||||||
|
checksum: "sha256:{{ dev_nix_installer_sha256 }}"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
# 3) Run Nix installer in daemon (multi-user) mode if Nix is not installed
|
||||||
|
- name: Run Nix installer in daemon (multi-user) mode if Nix is not installed
|
||||||
|
ansible.builtin.shell: >
|
||||||
|
"{{ dev_nix_installer_dest }}" --daemon
|
||||||
|
args:
|
||||||
|
creates: "/nix/store"
|
||||||
|
become: true
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
# Install Nix using a locally stored installer script with SHA256 verification.
|
|
||||||
|
|
||||||
- name: Ensure Nix installer script is present on target
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "{{ dev_nix_installer_source }}"
|
|
||||||
dest: "{{ dev_nix_installer_dest }}"
|
|
||||||
mode: "0755"
|
|
||||||
become: true
|
|
||||||
|
|
||||||
- name: Verify Nix installer SHA256 checksum
|
|
||||||
ansible.builtin.command: >
|
|
||||||
sh -c "sha256sum '{{ dev_nix_installer_dest }}' | awk '{print $1}'"
|
|
||||||
register: dev_nix_checksum_result
|
|
||||||
changed_when: false
|
|
||||||
become: true
|
|
||||||
|
|
||||||
- name: Fail if Nix installer checksum does not match
|
|
||||||
ansible.builtin.fail:
|
|
||||||
msg: >-
|
|
||||||
Nix installer checksum mismatch.
|
|
||||||
Expected '{{ dev_nix_installer_sha256 }}', got '{{ dev_nix_checksum_result.stdout }}'.
|
|
||||||
Refusing to execute the installer.
|
|
||||||
when: dev_nix_checksum_result.stdout != dev_nix_installer_sha256
|
|
||||||
|
|
||||||
# Nix multi-user (daemon) mode: creates /nix/store when successful.
|
|
||||||
- name: Run Nix installer in daemon (multi-user) mode if Nix is not installed
|
|
||||||
ansible.builtin.shell: >
|
|
||||||
"{{ dev_nix_installer_dest }}" --daemon
|
|
||||||
args:
|
|
||||||
creates: "/nix/store"
|
|
||||||
become: true
|
|
||||||
|
|
||||||
- name: Optionally drop shell snippet for Nix
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: "{{ dev_nix_shell_snippet_path }}"
|
|
||||||
mode: "0644"
|
|
||||||
content: |
|
|
||||||
# Added by dev-nix Ansible role
|
|
||||||
if [ -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
|
|
||||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
|
||||||
fi
|
|
||||||
when: dev_nix_enable_shell_snippet | bool
|
|
||||||
become: true
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
---
|
---
|
||||||
# Main entrypoint for the dev-nix role
|
- include_tasks: 01_core.yml
|
||||||
|
when: run_once_dev_nix is not defined
|
||||||
- name: Include installation tasks for Nix
|
|
||||||
ansible.builtin.include_tasks: install.yml
|
|
||||||
|
|||||||
12
roles/dev-nix/templates/nix.conf.j2
Normal file
12
roles/dev-nix/templates/nix.conf.j2
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Nix configuration file
|
||||||
|
# Managed by the {{ SOFTWARE_NAME }}dev-nix Ansible role
|
||||||
|
|
||||||
|
# Unix group containing the Nix build user accounts
|
||||||
|
build-users-group = nixbld
|
||||||
|
|
||||||
|
# Enable experimental features if configured
|
||||||
|
{% if dev_nix_enable_experimental_features %}
|
||||||
|
experimental-features = {{ dev_nix_experimental_features | join(" ") }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# (Optional) Add more global nix.conf options below
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
- name: update pkgmgr
|
- name: update pkgmgr
|
||||||
shell: |
|
shell: |
|
||||||
source ~/.venvs/pkgmgr/bin/activate
|
source ~/.venvs/pkgmgr/bin/activate
|
||||||
pkgmgr update pkgmgr
|
pkgmgr update pkgmgr --clone-mode shallow
|
||||||
register: pkgmgr_update
|
register: pkgmgr_update
|
||||||
changed_when: "'already up to date' not in (pkgmgr_update.stdout | lower)"
|
changed_when: "'already up to date' not in (pkgmgr_update.stdout | lower)"
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
include_role:
|
include_role:
|
||||||
name: '{{ item }}'
|
name: '{{ item }}'
|
||||||
loop:
|
loop:
|
||||||
- dev-git
|
- dev-git
|
||||||
- dev-make
|
- dev-make
|
||||||
- dev-python-yaml
|
- dev-nix
|
||||||
|
|
||||||
- name: Ensure OpenSSH client is installed
|
- name: Ensure OpenSSH client is installed
|
||||||
community.general.pacman:
|
community.general.pacman:
|
||||||
@@ -27,7 +27,21 @@
|
|||||||
mode: '0755'
|
mode: '0755'
|
||||||
become: true
|
become: true
|
||||||
|
|
||||||
- name: Clone Kevin's Package Manager repository
|
- name: Check if pkgmgr git repo already exists
|
||||||
|
stat:
|
||||||
|
path: "{{ PKGMGR_INSTALL_PATH }}/.git"
|
||||||
|
register: pkgmgr_git_repo
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Remove legacy 'latest' tag from existing pkgmgr repo (if present)
|
||||||
|
command: git tag -d latest
|
||||||
|
args:
|
||||||
|
chdir: "{{ PKGMGR_INSTALL_PATH }}"
|
||||||
|
when: pkgmgr_git_repo.stat.exists
|
||||||
|
ignore_errors: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Clone Kevin's Package Manager repository (always latest HEAD)
|
||||||
git:
|
git:
|
||||||
repo: "{{ PKGMGR_REPO_URL }}"
|
repo: "{{ PKGMGR_REPO_URL }}"
|
||||||
dest: "{{ PKGMGR_INSTALL_PATH }}"
|
dest: "{{ PKGMGR_INSTALL_PATH }}"
|
||||||
@@ -52,7 +66,7 @@
|
|||||||
become: true
|
become: true
|
||||||
|
|
||||||
- name: "Update all repositories with pkgmgr"
|
- name: "Update all repositories with pkgmgr"
|
||||||
command: "pkgmgr pull --all"
|
command: "pkgmgr update --all --clone-mode shallow"
|
||||||
when: MODE_UPDATE | bool
|
when: MODE_UPDATE | bool
|
||||||
|
|
||||||
- include_tasks: utils/once/flag.yml
|
- include_tasks: utils/once/flag.yml
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
# tests/integration/test_no_module_redirections_in_logs.py
|
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
import re
|
|
||||||
import unittest
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
REDIR_RE = re.compile(r"redirecting \(type: modules\)\s+(\S+)\s+to\s+(\S+)", re.IGNORECASE)
|
|
||||||
|
|
||||||
class ModuleRedirectionLogTest(unittest.TestCase):
|
|
||||||
"""
|
|
||||||
Fail if logs/*.log contains Ansible module redirections like:
|
|
||||||
'redirecting (type: modules) ansible.builtin.pacman to community.general.pacman'
|
|
||||||
Rationale: These lookups add overhead and clutter logs. Use fully-qualified
|
|
||||||
collection names directly in tasks to improve performance and clarity.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def test_no_module_redirections(self):
|
|
||||||
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
||||||
log_glob = os.path.join(project_root, "logs", "*.log")
|
|
||||||
files = sorted(glob.glob(log_glob))
|
|
||||||
|
|
||||||
if not files:
|
|
||||||
self.skipTest(f"No log files found at {log_glob}")
|
|
||||||
|
|
||||||
hits = []
|
|
||||||
mappings = defaultdict(int)
|
|
||||||
|
|
||||||
for path in files:
|
|
||||||
try:
|
|
||||||
with open(path, "r", encoding="utf-8", errors="replace") as fh:
|
|
||||||
for lineno, line in enumerate(fh, 1):
|
|
||||||
m = REDIR_RE.search(line)
|
|
||||||
if m:
|
|
||||||
src, dst = m.group(1), m.group(2)
|
|
||||||
hits.append((path, lineno, src, dst, line.strip()))
|
|
||||||
mappings[(src, dst)] += 1
|
|
||||||
except OSError as e:
|
|
||||||
self.fail(f"Cannot read log file {path}: {e}")
|
|
||||||
|
|
||||||
if hits:
|
|
||||||
# Build helpful failure message
|
|
||||||
suggestions = []
|
|
||||||
regex_hints = []
|
|
||||||
for (src, dst), count in sorted(mappings.items(), key=lambda x: (-x[1], x[0])):
|
|
||||||
suggestions.append(f"- Replace '{src}' with '{dst}' in your tasks ({count} occurrences).")
|
|
||||||
# Create VS Code regex for finding these in YAML
|
|
||||||
src_name = re.escape(src.split('.')[-1]) # only short module name
|
|
||||||
regex_hints.append(f"(?<!{re.escape(dst.rsplit('.',1)[0])}\\.){src_name}:")
|
|
||||||
|
|
||||||
examples = []
|
|
||||||
for i, (path, lineno, src, dst, text) in enumerate(hits[:10], 1):
|
|
||||||
examples.append(f"{i:02d}. {path}:{lineno}: {text}")
|
|
||||||
|
|
||||||
msg = (
|
|
||||||
f"Found {len(hits)} Ansible module redirections in logs/*.log.\n"
|
|
||||||
f"These slow down execution and clutter logs. "
|
|
||||||
f"Use fully-qualified module names to avoid runtime redirection.\n\n"
|
|
||||||
f"Suggested replacements:\n"
|
|
||||||
+ "\n".join(suggestions)
|
|
||||||
+ "\n\nExamples:\n"
|
|
||||||
+ "\n".join(examples)
|
|
||||||
+ "\n\nVS Code regex to find each occurrence in your code:\n"
|
|
||||||
+ "\n".join(f"- {hint}" for hint in sorted(set(regex_hints)))
|
|
||||||
+ "\n\nExample fix:\n"
|
|
||||||
f" # Instead of:\n"
|
|
||||||
f" pacman:\n"
|
|
||||||
f" # Use:\n"
|
|
||||||
f" community.general.pacman:\n"
|
|
||||||
)
|
|
||||||
self.fail(msg)
|
|
||||||
Reference in New Issue
Block a user