3 Commits

Author SHA1 Message Date
5edb3c08a2 fix(role): Install tmux-resurrect on Arch Linux from AUR 2025-08-21 04:08:51 +02:00
54d2327ec8 fix(role): Make config deletion more robust
We previously attempted to delete a file even if none was present.
This is now fixed.
2025-08-21 04:08:31 +02:00
f122b06697 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.
2025-08-21 03:48:22 +02:00
6 changed files with 144 additions and 20 deletions

View File

@@ -44,6 +44,7 @@ packages_linux_paru_archlinux:
- 'flent'
- 'mmv'
- 'paccache-hook'
- 'tmux-resurrect'
packages_linux_common_debian:
- 'apt-file'
@@ -56,3 +57,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'

View File

@@ -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 and stat_result.stat.exists'
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'

View File

@@ -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: '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 Arch Linux and ''tmux-resurrect'' package is absent and system-wide config file ''{{ tmux_global_config_file }}'' is present remove config block from file'
when: '(ansible_facts[''os_family''] | lower == ''archlinux'') and (''tmux-resurrect'' not in ansible_facts.packages) and (role_common_packages__tmux_global_config_file_stats.stat.exists)'
ansible.builtin.blockinfile:
marker: '# {mark} ANSIBLE MANAGED BLOCK - tmux-resurrect'
path: '{{ tmux_global_config_file }}'
state: 'absent'
block: '{{ tmux_global_config_resurrect }}'
- 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'

View File

@@ -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'

23
tasks/base-packages.yml Normal file
View File

@@ -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'

View File

@@ -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'''