feat(cli): install ci shell completion via install-ci-alias.sh
Generate a click completion file for bash/zsh and source it from the alias block. Click's generated script queries completions by invoking the command — but `ci` is a sudo shell function (env vars don't survive sudo, and `env VAR=x ci` can't call a function), so rewrite the query to call the venv python directly (read-only, no sudo) and drop zsh's `$+commands[ci]` guard. Writes ~/.ci-completion.<shell>; removed cleanly on --uninstall (block strip).
This commit is contained in:
@@ -24,14 +24,37 @@ log() { printf '[install-ci-alias] %s\n' "$*"; }
|
|||||||
die() { printf '[install-ci-alias] ERROR: %s\n' "$*" >&2; exit 1; }
|
die() { printf '[install-ci-alias] ERROR: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
block() {
|
block() {
|
||||||
|
# $1 (optional): path to a shell-completion file to source from the block.
|
||||||
|
local cmpl="${1:-}"
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
${MARK_BEGIN}
|
${MARK_BEGIN}
|
||||||
# Run the CI orchestrator as the ${RUN_USER} service user (production venv).
|
# Run the CI orchestrator as the ${RUN_USER} service user (production venv).
|
||||||
ci() { sudo -u ${RUN_USER} ${PROD_PY} -m ci_orchestrator "\$@"; }
|
ci() { sudo -u ${RUN_USER} ${PROD_PY} -m ci_orchestrator "\$@"; }
|
||||||
# Same, but as the current user (no sudo) — handy for read-only commands.
|
# Same, but as the current user (no sudo) — handy for read-only commands.
|
||||||
ci-me() { ${PROD_PY} -m ci_orchestrator "\$@"; }
|
ci-me() { ${PROD_PY} -m ci_orchestrator "\$@"; }
|
||||||
${MARK_END}
|
|
||||||
EOF
|
EOF
|
||||||
|
[ -n "$cmpl" ] && printf '[ -f "%s" ] && source "%s"\n' "$cmpl" "$cmpl"
|
||||||
|
printf '%s\n' "${MARK_END}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate a click shell-completion file for `ci`. Click's generated script
|
||||||
|
# calls the command (`ci`) to query completions, but `ci` is a sudo shell
|
||||||
|
# function — env vars don't survive sudo and `env VAR=x ci` can't call a
|
||||||
|
# function. Rewrite the query to call the venv python directly (read-only, no
|
||||||
|
# sudo) and drop zsh's `$+commands[ci]` guard (ci is a function, not on PATH).
|
||||||
|
gen_completion() {
|
||||||
|
local out="$1" shell="$2"
|
||||||
|
case "$shell" in
|
||||||
|
zsh)
|
||||||
|
_CI_COMPLETE=zsh_source "$PROD_PY" -m ci_orchestrator 2>/dev/null \
|
||||||
|
| sed -e "s#_CI_COMPLETE=zsh_complete ci)#_CI_COMPLETE=zsh_complete ${PROD_PY} -m ci_orchestrator)#" \
|
||||||
|
-e '/\$+commands\[ci\]/d' > "$out" ;;
|
||||||
|
bash)
|
||||||
|
_CI_COMPLETE=bash_source "$PROD_PY" -m ci_orchestrator 2>/dev/null \
|
||||||
|
| sed -e "s#_CI_COMPLETE=bash_complete \$1#_CI_COMPLETE=bash_complete ${PROD_PY} -m ci_orchestrator#" > "$out" ;;
|
||||||
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
|
[ -s "$out" ] || { rm -f "$out"; return 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
strip_block() {
|
strip_block() {
|
||||||
@@ -47,9 +70,22 @@ strip_block() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_into() {
|
install_into() {
|
||||||
local file="$1"
|
local file="$1" shell="" cmpl=""
|
||||||
|
case "$file" in
|
||||||
|
*.zshrc) shell="zsh" ;;
|
||||||
|
*.bashrc) shell="bash" ;;
|
||||||
|
esac
|
||||||
|
if [ -n "$shell" ] && [ -x "$PROD_PY" ]; then
|
||||||
|
cmpl="$HOME/.ci-completion.$shell"
|
||||||
|
if gen_completion "$cmpl" "$shell"; then
|
||||||
|
log "wrote $shell completion: $cmpl"
|
||||||
|
else
|
||||||
|
cmpl=""
|
||||||
|
log "WARNING: could not generate $shell completion — skipped (alias still installed)."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
strip_block "$file"
|
strip_block "$file"
|
||||||
{ printf '\n'; block; } >> "$file"
|
{ printf '\n'; block "$cmpl"; } >> "$file"
|
||||||
log "updated $file"
|
log "updated $file"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user