From f122b06697ff82453cd8aa3cf9ad1da2f119c99e Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Thu, 21 Aug 2025 03:48:22 +0200 Subject: [PATCH] feat(role): Add package-specific global config files Packages can now have a global (i.e. system-wide) config defined and applied. If package is missing the config file is deleted. This is helpful for example for Git where we want to define helpful aliases for every logged in user and for tmux where every user should have access to the tmux-resurrect session manager etc. --- defaults/main.yml | 43 +++++++++++++++++++ ...-settings-single-package-single-config.yml | 41 ++++++++++++++++++ .../base-package-auxiliary-settings-tmux.yml | 31 +++++++++++++ tasks/base-package-auxiliary-settings.yml | 3 ++ tasks/base-packages.yml | 23 ++++++++++ tasks/main.yml | 22 +--------- 6 files changed, 143 insertions(+), 20 deletions(-) create mode 100644 tasks/base-package-auxiliary-settings-single-package-single-config.yml create mode 100644 tasks/base-package-auxiliary-settings-tmux.yml create mode 100644 tasks/base-package-auxiliary-settings.yml create mode 100644 tasks/base-packages.yml diff --git a/defaults/main.yml b/defaults/main.yml index 324df00..6d4a91a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -56,3 +56,46 @@ packages_linux_common_debian: - 'netcat-openbsd' - 'unattended-upgrades' - 'xxd' + +package_config: + - name: 'tmux' + global_config_file: '/etc/tmux.conf' + marker: 'sane defaults' + global_config: | + # Renumber windows when one is deleted + set-option -g renumber-windows on + + # Enable mouse control (clickable windows, panes, resizable panes) + set -g mouse on + - name: 'git' + global_config_file: '/etc/gitconfig' + marker: 'sane defaults' + global_config: | + [alias] + # https://stackoverflow.com/a/30998048 + # Find merge that contains a given commit + find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'" + + # https://stackoverflow.com/a/30998048 + # Show merge commit msg and other details of merge commit + # that contains a given commit + show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'" + + # https://stackoverflow.com/a/23508223 + # Show all commits that are part of a merge commit + log-merge = "!f() { git log --stat \"$1^..$1\"; }; f" + +tmux_global_config_file: '/etc/tmux.conf' +tmux_global_config_resurrect: | + # Auto-load tmux-resurrect + # prefix + Ctrl-s - save + # prefix + Ctrl-r - restore + run-shell /usr/share/tmux-resurrect/resurrect.tmux + + # Restore pane content (not just running commands) + # This will e.g. show the last 'ls' output you did in a pane + set -g @resurrect-capture-pane-contents 'on' + + # Restore a few additional processes beyond the conservative default of + # vi vim nvim emacs man less more tail top htop irssi weechat mutt + set -g @resurrect-processes 'btop journalctl ncdu watch' diff --git a/tasks/base-package-auxiliary-settings-single-package-single-config.yml b/tasks/base-package-auxiliary-settings-single-package-single-config.yml new file mode 100644 index 0000000..5d0d5b0 --- /dev/null +++ b/tasks/base-package-auxiliary-settings-single-package-single-config.yml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: MIT + +# This file adds config blocks to files that are dependent on a single package +# being present. If for example the 'git' package is present we want content in +# Git's global '/etc/gitconfig' file. If the package is absent that file content +# is removed. If after that the file is empty (i.e. has a size of 0 bytes) the +# file is deleted. + +- name: 'Add per-package config' + when: 'pkg.name in ansible_facts.packages' + loop_control: + loop_var: 'pkg' + label: 'If ''{{ pkg.name }}'' package is present set system-wide config in ''{{ pkg.global_config_file }}''' + loop: '{{ package_config }}' + ansible.builtin.blockinfile: + marker: '# {mark} ANSIBLE MANAGED BLOCK - {{ pkg.name }} {{ pkg.marker }}' + path: '{{ pkg.global_config_file }}' + append_newline: true + prepend_newline: true + state: 'present' + create: true + block: '{{ pkg.global_config }}' + +- name: 'Get stats of global config files' + register: 'role_common_packages__global_config_file_stats' + loop_control: + loop_var: 'pkg' + label: 'Get stats of ''{{ pkg.name }}'' system-wide config file ''{{ pkg.global_config_file }}''' + loop: '{{ package_config }}' + ansible.builtin.stat: + path: '{{ pkg.global_config_file }}' + +- name: 'Remove per-package config' + when: 'stat_result.pkg.name not in ansible_facts.packages' + loop_control: + loop_var: 'stat_result' + label: 'If ''{{ stat_result.pkg.name }}'' package is absent and system-wide config file ''{{ stat_result.pkg.global_config_file }}'' is present remove config file' + loop: '{{ role_common_packages__global_config_file_stats.results }}' + ansible.builtin.file: + path: '{{ stat_result.pkg.global_config_file }}' + state: 'absent' diff --git a/tasks/base-package-auxiliary-settings-tmux.yml b/tasks/base-package-auxiliary-settings-tmux.yml new file mode 100644 index 0000000..00125a1 --- /dev/null +++ b/tasks/base-package-auxiliary-settings-tmux.yml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: MIT +- name: 'If Arch Linux and if ''tmux-resurrect'' and ''tmux'' packages are present auto-load tmux-resurrect on tmux start system-wide' + when: '(ansible_facts[''os_family''] | lower == ''archlinux'') and (''tmux-resurrect'' in ansible_facts.packages) and (''tmux'' in ansible_facts.packages)' + ansible.builtin.blockinfile: + marker: '# {mark} ANSIBLE MANAGED BLOCK - tmux-resurrect' + path: '{{ tmux_global_config_file }}' + append_newline: true + prepend_newline: true + state: 'present' + create: true + block: '{{ tmux_global_config_resurrect }}' + +- name: 'If Arch Linux and ''tmux-resurrect'' package is absent never auto-load tmux-resurrect on tmux start system-wide' + when: '(ansible_facts[''os_family''] | lower == ''archlinux'') and (''tmux-resurrect'' not in ansible_facts.packages)' + ansible.builtin.blockinfile: + marker: '# {mark} ANSIBLE MANAGED BLOCK - tmux-resurrect' + path: '{{ tmux_global_config_file }}' + state: 'absent' + block: '{{ tmux_global_config_resurrect }}' + +- name: 'Get stats of ''{{ tmux_global_config_file }}''' + ansible.builtin.stat: + path: '{{ tmux_global_config_file }}' + register: 'role_common_packages__tmux_global_config_file_stats' + +- name: 'If ''{{ tmux_global_config_file }}'' is 0 bytes delete it' + when: 'role_common_packages__tmux_global_config_file_stats.stat.size == 0' + ansible.builtin.file: + path: '{{ tmux_global_config_file }}' + state: 'absent' + diff --git a/tasks/base-package-auxiliary-settings.yml b/tasks/base-package-auxiliary-settings.yml new file mode 100644 index 0000000..22406b7 --- /dev/null +++ b/tasks/base-package-auxiliary-settings.yml @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT +- import_tasks: 'base-package-auxiliary-settings-tmux.yml' +- import_tasks: 'base-package-auxiliary-settings-single-package-single-config.yml' diff --git a/tasks/base-packages.yml b/tasks/base-packages.yml new file mode 100644 index 0000000..48a70eb --- /dev/null +++ b/tasks/base-packages.yml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: MIT +- name: 'Gather package facts' + ansible.builtin.package_facts: + manager: 'auto' + +- name: 'If OS is a Linux flavor install Linux-specific packages' + when: 'ansible_facts[''system''] | lower == ''linux''' + ansible.builtin.package: + name: '{{ packages_linux_common_all_families }}' + state: 'present' + +- name: 'If ''os_family'' is ''{{ ansible_facts[''os_family''] | lower }}'' install {{ ansible_facts[''os_family''] | lower }}-specific packages' + ansible.builtin.package: + name: '{{ vars[''packages_linux_common_'' + ansible_facts[''os_family''] | lower] }}' + state: 'present' + +- name: 'If Arch Linux install Arch User Repository (AUR) packages' + when: 'ansible_facts[''os_family''] | lower == ''archlinux''' + kewlfft.aur.aur: + name: '{{ packages_linux_paru_archlinux }}' + state: 'present' + become: 'yes' + become_user: 'build' diff --git a/tasks/main.yml b/tasks/main.yml index a9518ca..a401ef7 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,25 +1,7 @@ # SPDX-License-Identifier: MIT -- name: 'If OS is a Linux flavor install Linux-specific packages' - when: 'ansible_facts[''system''] | lower == ''linux''' - ansible.builtin.package: - name: '{{ packages_linux_common_all_families }}' - state: 'present' - -- name: 'If ''os_family'' is ''{{ ansible_facts[''os_family''] | lower }}'' install {{ ansible_facts[''os_family''] | lower }}-specific packages' - ansible.builtin.package: - name: '{{ vars[''packages_linux_common_'' + ansible_facts[''os_family''] | lower] }}' - state: 'present' - -- name: 'If Arch Linux install Arch User Repository (AUR) packages' - when: 'ansible_facts[''os_family''] | lower == ''archlinux''' - kewlfft.aur.aur: - name: '{{ packages_linux_paru_archlinux }}' - state: 'present' - become: 'yes' - become_user: 'build' - +- import_tasks: 'base-packages.yml' +- import_tasks: 'base-package-auxiliary-settings.yml' - import_tasks: 'arch-linux-local-aur-repo-chroot.yml' when: 'ansible_facts[''os_family''] | lower == ''archlinux''' - - import_tasks: 'maintenance-unattended-upgrades.yml' when: 'ansible_facts[''os_family''] | lower == ''debian'''