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 <noreply@anthropic.com>
This commit is contained in:
Executable
+105
@@ -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 <<EOF
|
||||
${MARK_BEGIN}
|
||||
# Run the CI orchestrator as the ${RUN_USER} service user (production venv).
|
||||
ci() { sudo -u ${RUN_USER} ${PROD_PY} -m ci_orchestrator "\$@"; }
|
||||
# Same, but as the current user (no sudo) — handy for read-only commands.
|
||||
ci-me() { ${PROD_PY} -m ci_orchestrator "\$@"; }
|
||||
${MARK_END}
|
||||
EOF
|
||||
}
|
||||
|
||||
strip_block() {
|
||||
# Remove an existing marked block from $1 (in place). No-op if absent.
|
||||
local file="$1"
|
||||
[ -f "$file" ] || return 0
|
||||
if grep -qF "$MARK_BEGIN" "$file"; then
|
||||
# Delete everything between the markers, inclusive.
|
||||
sed -i "/$(printf '%s' "$MARK_BEGIN" | sed 's/[].[*^$/]/\\&/g')/,/$(printf '%s' "$MARK_END" | sed 's/[].[*^$/]/\\&/g')/d" "$file"
|
||||
# Drop a possible trailing blank line left behind.
|
||||
sed -i -e :a -e '/^\n*$/{$d;N;ba}' "$file" 2>/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 "$@"
|
||||
+23
-9
@@ -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 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user