From 2241d6af7f43d6d2ebf0bc0347408ed8fe33e0e2 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 8 Jun 2026 00:11:36 +0200 Subject: [PATCH] feat(setup): add `ci` shell alias helper + install it from setup-host scripts/install-ci-alias.sh installs `ci` (runs the orchestrator as ci-runner via the prod venv) and `ci-me` (current user). Idempotent, marker-bounded; supports --system (/etc/profile.d), --uninstall. setup-host-linux.sh gains a step [7/7] that installs it system-wide, passing CI_PROD_PYTHON/CI_RUN_USER. Co-Authored-By: Claude Opus 4.8 --- scripts/install-ci-alias.sh | 105 ++++++++++++++++++++++++++++++++++++ setup-host-linux.sh | 32 +++++++---- 2 files changed, 128 insertions(+), 9 deletions(-) create mode 100755 scripts/install-ci-alias.sh diff --git a/scripts/install-ci-alias.sh b/scripts/install-ci-alias.sh new file mode 100755 index 0000000..dd3aa13 --- /dev/null +++ b/scripts/install-ci-alias.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +# install-ci-alias.sh — install a `ci` shell helper that runs the CI +# orchestrator as the ci-runner service user against the production venv. +# +# After install: ci validate host == sudo -u ci-runner \ +# /opt/ci/venv/bin/python -m ci_orchestrator validate host +# +# Usage: +# ./scripts/install-ci-alias.sh # install into the current user's +# # ~/.bashrc and ~/.zshrc (if present) +# ./scripts/install-ci-alias.sh --system # install system-wide via +# # /etc/profile.d/ci-alias.sh (needs sudo) +# ./scripts/install-ci-alias.sh --uninstall # remove the installed block +# +# Idempotent: re-running updates the block in place instead of duplicating it. +set -euo pipefail + +PROD_PY="${CI_PROD_PYTHON:-/opt/ci/venv/bin/python}" +RUN_USER="${CI_RUN_USER:-ci-runner}" +MARK_BEGIN="# >>> ci-orchestrator alias >>>" +MARK_END="# <<< ci-orchestrator alias <<<" + +log() { printf '[install-ci-alias] %s\n' "$*"; } +die() { printf '[install-ci-alias] ERROR: %s\n' "$*" >&2; exit 1; } + +block() { + cat </dev/null || true + fi +} + +install_into() { + local file="$1" + strip_block "$file" + { printf '\n'; block; } >> "$file" + log "updated $file" +} + +uninstall_from() { + local file="$1" + if [ -f "$file" ] && grep -qF "$MARK_BEGIN" "$file"; then + strip_block "$file" + log "removed block from $file" + fi +} + +main() { + local mode="user" action="install" + case "${1:-}" in + --system) mode="system" ;; + --uninstall) action="uninstall" ;; + "" ) ;; + * ) die "unknown argument: $1 (use --system or --uninstall)" ;; + esac + + # Sanity: warn (don't fail) if the production venv is missing. + [ -x "$PROD_PY" ] || log "WARNING: $PROD_PY not found — alias installed anyway; fix the venv before use." + + if [ "$mode" = "system" ]; then + local target="/etc/profile.d/ci-alias.sh" + if [ "$action" = "uninstall" ]; then + sudo rm -f "$target" && log "removed $target" + else + block | sudo tee "$target" >/dev/null + sudo chmod 0644 "$target" + log "installed $target (applies to all login shells)" + fi + else + local files=() + [ -f "$HOME/.bashrc" ] && files+=("$HOME/.bashrc") + [ -f "$HOME/.zshrc" ] && files+=("$HOME/.zshrc") + # If neither exists, create ~/.bashrc so the alias lands somewhere. + [ ${#files[@]} -eq 0 ] && files+=("$HOME/.bashrc") + + for f in "${files[@]}"; do + if [ "$action" = "uninstall" ]; then uninstall_from "$f"; else install_into "$f"; fi + done + fi + + if [ "$action" = "install" ]; then + log "done. Open a new shell, or run: source ~/.bashrc" + log "try: ci validate host" + else + log "done. Open a new shell to drop the alias." + fi +} + +main "$@" diff --git a/setup-host-linux.sh b/setup-host-linux.sh index 31bb6db..ff04e0e 100755 --- a/setup-host-linux.sh +++ b/setup-host-linux.sh @@ -13,6 +13,7 @@ # 4. Installa Python 3.11+ e crea venv produzione in /opt/ci/venv # 5. (Opzionale) Clona il repo e installa il package nel venv # 6. (Opt-in, --with-pwsh) Installa PowerShell Core +# 7. Installa l'alias shell `ci` a livello di sistema (/etc/profile.d/) # L'host Linux NON ha più bisogno di pwsh per il normale funzionamento # (orchestratore Python). Installalo solo se ti serve per script legacy. @@ -93,7 +94,7 @@ echo " Utente : $CI_USER" echo "" # ── Step 1: utente di servizio ──────────────────────────────────────────────── -info "[1/6] Utente di servizio $CI_USER" +info "[1/7] Utente di servizio $CI_USER" if id "$CI_USER" &>/dev/null; then warn "Utente $CI_USER esiste già — skip" else @@ -102,7 +103,7 @@ else fi # ── Step 2: mount partizione CI ─────────────────────────────────────────────── -info "[2/6] Mount $CI_DISK → $CI_ROOT" +info "[2/7] Mount $CI_DISK → $CI_ROOT" if mountpoint -q "$CI_ROOT" 2>/dev/null; then warn "$CI_ROOT già montato — skip riorganizzazione e fstab" @@ -160,7 +161,7 @@ else fi # ── Step 3: layout directory e permessi ─────────────────────────────────────── -info "[3/6] Layout directory e permessi" +info "[3/7] Layout directory e permessi" # Installa acl se mancante if ! command -v setfacl &>/dev/null; then @@ -186,7 +187,7 @@ echo " Layout OK — ACL default su build-vms applicata" # ── Step 4: Python 3.11+ e venv ────────────────────────────────────────────── if [[ "$SKIP_PYTHON" == false ]]; then - info "[4/6] Python 3.11+ e venv produzione" + info "[4/7] Python 3.11+ e venv produzione" # Cerca la prima versione di Python >= 3.11 già installata PYTHON_BIN="" @@ -217,12 +218,12 @@ if [[ "$SKIP_PYTHON" == false ]]; then echo " venv creato in $OPT_CI/venv ($($PYTHON_BIN --version))" fi else - info "[4/6] Python/venv — SKIPPED" + info "[4/7] Python/venv — SKIPPED" fi # ── Step 5: Clone repo e pip install ───────────────────────────────────────── if [[ "$SKIP_CLONE" == false ]]; then - info "[5/6] Clone repo e pip install" + info "[5/7] Clone repo e pip install" REPO_DIR="$OPT_CI/local-ci-cd-system" if [[ -d "$REPO_DIR/.git" ]]; then warn "Repo già presente in $REPO_DIR — skip clone (eseguire git pull manualmente)" @@ -236,12 +237,12 @@ if [[ "$SKIP_CLONE" == false ]]; then || die "ci_orchestrator non importabile" echo " Verifica OK: ${verify_out%%$'\n'*}" else - info "[5/6] Clone repo — SKIPPED" + info "[5/7] Clone repo — SKIPPED" fi # ── Step 6: PowerShell Core (opt-in via --with-pwsh) ────────────────────────── if [[ "$WITH_PWSH" == true ]]; then - info "[6/6] PowerShell Core" + info "[6/7] PowerShell Core" if command -v pwsh &>/dev/null; then warn "pwsh già installato: $(pwsh --version) — skip" else @@ -263,7 +264,20 @@ if [[ "$WITH_PWSH" == true ]]; then echo " Installato: $(pwsh --version)" fi else - info "[6/6] PowerShell Core — SKIPPED (opt-in con --with-pwsh)" + info "[6/7] PowerShell Core — SKIPPED (opt-in con --with-pwsh)" +fi + +# ── Step 7: alias shell `ci` (system-wide) ──────────────────────────────────── +info "[7/7] Alias shell 'ci'" +ALIAS_SCRIPT="$OPT_CI/local-ci-cd-system/scripts/install-ci-alias.sh" +if [[ -x "$ALIAS_SCRIPT" ]]; then + # Installa /etc/profile.d/ci-alias.sh per tutti gli utenti login. + # Passa il venv/utente correnti così l'alias punta a questa installazione. + CI_PROD_PYTHON="$OPT_CI/venv/bin/python" CI_RUN_USER="$CI_USER" \ + bash "$ALIAS_SCRIPT" --system + echo " Alias 'ci' installato — apri una nuova shell e prova: ci validate host" +else + warn "install-ci-alias.sh non trovato in $ALIAS_SCRIPT — skip (clona il repo, Step 5)" fi # ── Riepilogo ─────────────────────────────────────────────────────────────────