From 77bff27f08e116d08bab5ad1294b48154b146d7a Mon Sep 17 00:00:00 2001 From: Brant Evans Date: Fri, 12 Jun 2026 17:28:35 -0700 Subject: [PATCH 1/2] feat(install_cloud_clis): lazy-load and cache bash completions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace eager `source <(cmd completion bash)` calls with a `_lazy_completion` function that defers completion generation to first tab-complete, caches output under ~/.cache/bash_completions/, and auto-invalidates when the CLI binary is updated. This eliminates subprocess spawns at shell startup for ~8 CLIs. AWS CLI is unchanged — it already uses a direct binary completer. Co-Authored-By: Claude Opus 4.6 --- roles/install_cloud_clis/README.md | 2 +- .../templates/bashrc_cloud_cli_completion.j2 | 67 ++++++++----------- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/roles/install_cloud_clis/README.md b/roles/install_cloud_clis/README.md index f281e05..d067041 100644 --- a/roles/install_cloud_clis/README.md +++ b/roles/install_cloud_clis/README.md @@ -87,7 +87,7 @@ When `install_cloud_clis_manage_bashrc_completion` is `true`, the role writes on `# BEGIN ANSIBLE MANAGED BLOCK branic.system_management.install_cloud_clis` and `# END ANSIBLE MANAGED BLOCK branic.system_management.install_cloud_clis` -The block uses **`if command -v …; then` / `fi`** stanzas and `# shellcheck source=/dev/null` before `source <(…)` completions, matching common interactive shell style. Only CLIs listed in `install_cloud_clis_components` are included, in the same order as `install_cloud_clis_cli_installers` in [`vars/main.yml`](vars/main.yml). +The block defines a **`_lazy_completion`** shell function and registers one-liner calls for each CLI. Completions are deferred until the user's first tab-complete for a given command, then cached under **`~/.cache/bash_completions/`**. The cache auto-invalidates when the CLI binary is newer than the cached file. AWS CLI uses a direct binary completer (`aws_completer`) and does not use the lazy-load mechanism. Only CLIs listed in `install_cloud_clis_components` are included. `blockinfile` runs with **`backup: true`** (timestamped `.bashrc` backup beside the file) and sets **`mode: 0644`** on `.bashrc` when the module updates the file. Add your own completions **outside** that marked region (for example in `~/.bashrc-local` or after the block) so the role does not manage them. diff --git a/roles/install_cloud_clis/templates/bashrc_cloud_cli_completion.j2 b/roles/install_cloud_clis/templates/bashrc_cloud_cli_completion.j2 index 9b04afb..8051a54 100644 --- a/roles/install_cloud_clis/templates/bashrc_cloud_cli_completion.j2 +++ b/roles/install_cloud_clis/templates/bashrc_cloud_cli_completion.j2 @@ -5,58 +5,47 @@ if command -v aws &>/dev/null; then fi {% endif %} -{% if 'oc' in install_cloud_clis_components %} -if command -v oc &>/dev/null; then - # shellcheck source=/dev/null - source <(oc completion bash) -fi +{% set _lazy_cli_components = ['oc', 'ocm', 'rosa', 'tekton', 'kube_linter', 'kustomize', 'stern', 'helm'] %} +{% if _lazy_cli_components | intersect(install_cloud_clis_components) | length > 0 %} +_lazy_completion() { + local cmd=$1; shift + local gen_args=("$@") + local cache="${XDG_CACHE_HOME:-$HOME/.cache}/bash_completions/${cmd}.bash" + eval "_complete_lazy_${cmd}() { + unset -f _complete_lazy_${cmd} + complete -r ${cmd} 2>/dev/null + if [[ ! -f '${cache}' || \$(command -v ${cmd}) -nt '${cache}' ]]; then + mkdir -p '${XDG_CACHE_HOME:-$HOME/.cache}/bash_completions' + \"\${gen_args[@]}\" > '${cache}' + fi + source '${cache}' + return 124 + }" + complete -F "_complete_lazy_${cmd}" "$cmd" +} +{% if 'oc' in install_cloud_clis_components %} +command -v oc &>/dev/null && _lazy_completion oc oc completion bash {% endif %} {% if 'ocm' in install_cloud_clis_components %} -if command -v ocm &>/dev/null; then - # shellcheck source=/dev/null - source <(ocm completion bash) -fi - +command -v ocm &>/dev/null && _lazy_completion ocm ocm completion bash {% endif %} {% if 'rosa' in install_cloud_clis_components %} -if command -v rosa &>/dev/null; then - # shellcheck source=/dev/null - source <(rosa completion bash) -fi - +command -v rosa &>/dev/null && _lazy_completion rosa rosa completion bash {% endif %} {% if 'tekton' in install_cloud_clis_components %} -if command -v tkn &>/dev/null; then - # shellcheck source=/dev/null - source <(tkn completion bash) -fi - +command -v tkn &>/dev/null && _lazy_completion tkn tkn completion bash {% endif %} {% if 'kube_linter' in install_cloud_clis_components %} -if command -v kube-linter &>/dev/null; then - # shellcheck source=/dev/null - source <(kube-linter completion bash) -fi - +command -v kube-linter &>/dev/null && _lazy_completion kube-linter kube-linter completion bash {% endif %} {% if 'kustomize' in install_cloud_clis_components %} -if command -v kustomize &>/dev/null; then - # shellcheck source=/dev/null - source <(kustomize completion bash) -fi - +command -v kustomize &>/dev/null && _lazy_completion kustomize kustomize completion bash {% endif %} {% if 'stern' in install_cloud_clis_components %} -if command -v stern &>/dev/null; then - # shellcheck source=/dev/null - source <(stern --completion=bash) -fi - +command -v stern &>/dev/null && _lazy_completion stern stern --completion=bash {% endif %} {% if 'helm' in install_cloud_clis_components %} -if command -v helm &>/dev/null; then - # shellcheck source=/dev/null - source <(helm completion bash) -fi +command -v helm &>/dev/null && _lazy_completion helm helm completion bash +{% endif %} {% endif %} From be2dcfe60481e0a7973df8b1338dd7f6264dbb65 Mon Sep 17 00:00:00 2001 From: Brant Evans Date: Mon, 15 Jun 2026 08:58:46 -0700 Subject: [PATCH 2/2] docs: add changelog fragment for lazy-load bash completions Co-Authored-By: Claude Opus 4.6 --- changelogs/fragments/lazy-load-bash-completions.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelogs/fragments/lazy-load-bash-completions.yml diff --git a/changelogs/fragments/lazy-load-bash-completions.yml b/changelogs/fragments/lazy-load-bash-completions.yml new file mode 100644 index 0000000..8e488e6 --- /dev/null +++ b/changelogs/fragments/lazy-load-bash-completions.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - install_cloud_clis - lazy-load and cache bash completions to eliminate subprocess spawns at shell startup