updating documentation

- giving things a better structure
- better documentation with the way things need to be as a standard
This commit is contained in:
Matthew Stobbs
2026-02-04 22:26:15 -07:00
parent 4e65d36b64
commit e231c6ae7a
15 changed files with 221 additions and 194 deletions

View File

@@ -2,108 +2,83 @@
## Package definition ## Package definition
Package defintions are just `yaml` tasks in the directory A "package" is just a yaml task list that defines how to install a piece of software.
`tasks/pkgs`, which handle how a package is installed. It does this through the use of `helpers` that manage;
Most can be installed using the `syspkgs` list, and are simply - dependency installations
appending the package name to said list based on the system. - building from source
- linking binaries to a usable `PATH`
- calling external tools when required
- installation via package managers on the system
If a package can be installed via an entry to `syspkgs` for some, ## Anatomy of a Package Definition
but not all platforms, handling is done to either inform the user
that the package is not available, or to append the package name
to another installation method such as:
- `appimages` to install the appimage of a package It starts with package metadata, as a comment block above the installation steps.
- `cargopkgs` to install via the rust cargo package manager This should come after the line `# vim: set filetype=yaml.ansible :`, which sets
- `cargoversioned` to install version lockec cargo packages up the correct linter and language server when using neovim/vim.
- `caskpkgs` to install a homebrew cask
- `flatpkgs` to install flatpaks
- `gopkgs` to install using the `go install` command
- `npmpkgs` to install packages from npm
- `pipxpkgs` to install packages from Python pip
- `srcpkgs` to build packages from source
- `tappkgs` to install packages from home brew taps
Alternative sources of packages can be defined with entries to: ### Metadata
- `fpremotes` to add a flatpak remote The metadata consists of at minimum 6 key: value pairs
- `brewtaps` to add a homebrew tap
### Adding system level repositories
Many packages exist in their own external repository for the
given system, such as `/etc/yum.repos.d` for RedHat based linux
distros, `/etc/apt/sources.list.d` for Debian based distros and
others. Since you an add the package to `syspkgs` by enabling a
repo, the coresponding task in `tasks/pkgs` should take the
steps needed to enable the repository.
### Packages with multiple instllation methods
Many packages can be installed in different ways, like the
`bitwarden` package. `bitwarden` can be installed as a `syspkg`
on some machines, a `caskpkg` on macOS, an `appimage`, a `flatpak`
or even a `snap`.
For such packages, a default is chosen to install, in the following order
of precedence: `syspkgs`, `flatpkgs`, `snappkgs`, `appimages`.
In that order, `syspkgs` and `caskpkgs` have equal weight, as it applies
to macOS.
## Formatting rules
- Use indentation explicitness. Lists should be indented:
```yaml ```yaml
# Good # Package: <package name>
my_good_list: # Description: <package description>
- my_list_item # Version: <latest supported version of package. 'latest' is fine>
# Methods: <list of available methods for installation>
# Bad # Helpers: <list of helpers used by the package directly>
my_bad_list: # Maintainers: <list of maintainers for this package>
- my_list_item
``` ```
This list should match package defaults where it makes sense, for example,
the `Version:` should match the default installed version of the package.
- Variables should be in snake case, separating words ### Configuration acknowledgement
- Short names are fine if they are explicit. ie `vers` can be used instead of `version`
- If more then one variable starts with the same words, put it into a dict if it makes sense: The "Configuration acknowledgement" MUST be at the start of the yaml file,
and cover everything this package does. This is important for gating when
a package should be configured or not.
It looks like this, using the `air` package:
```yaml ```yaml
# variables that should be a dict - name: Start air configuration
cargo_locked: true
cargo_pkg: alacritty
# better to just be
cargo:
locked: true
pkg: alacritty
```
- Tasks **MUST** follow the convention in this example:
```yaml
- name: Capitalize first letter of name
when: when:
- each condition has it's own line - "'air' is not in __configured"
- (brackets around conditions with) or block:
(to show they are separate) - name: Configure air installation method
become: "{{ not use_local }}" # must be able to be used with use_local
become_user: # this should not be needed, but always follows become if it is
loop: "{{ my_loopable_list }}"
loop_control: # **MUST** always use at least loop_var for any loop
loop_var: my_item
ansible.builtin.set_fact: # always use the full module name
... ...
- name: Finalize air configuration
ansible.builtin.set_fact:
__air_configured: true
``` ```
- `name`: Every task needs a name, and the first letter must be capitalized or alternatively:
- `when`: If a when clause exists, it follows the name
- Each clause must have it's own line, including and `or` clause, as seen above ```yaml
- `become`: must follow the when clause if it exists, name otherwise - name: Start air configuration
- Any other `become_` settings follow `become` in alphabetical order when:
- `loop`: must be defined just before the module invocation - __configured['air'] is undefined
- Every loop needs to rename the `loop_var` to something that makes sense ```
- `until` is consider the same as `loop` for the purposes of placement
- The last item must be the module invocation, using the fully qualified name This way, if a package is included as part of another packages build, it only happens once.
- For example, don't use `set_fact:`, use `ansible.builtin.set_fact:`
### Setting and adding package configuration to list
Adding the configuration for a package is done by appending the configuration to the
appropriate list. Each helper has it's own installation block in `tasks/main.yml`.
Depending on the package installation method, the package must be added to the appropriate list.
#### Different lists, and when to use them
The following is a list of the different lists that are used, and the
order they are run.
- system: pkg_sys
- Only for packages installed from the system package manager
- If a package adds a repository to handle the system installation, it should be
done in the package configuration itself. For example, installing `ghostty` via
the system package manager requires adding a copr repo on fedora. This should be
done in a section named 'Adding copr repository scottames/ghostty'

View File

@@ -1,4 +1,5 @@
# ansible_role_package # Ansible package manager
## _A ports like system for ansible_
Manage package installation for a number of packages Manage package installation for a number of packages
that sometimes need special handling. Some are built from that sometimes need special handling. Some are built from
@@ -10,14 +11,16 @@ special instructions to properly install and use. I decided to
simplify the management of those packages by creating a role with simplify the management of those packages by creating a role with
special handling. special handling.
_The following are for general use. Not all packages have a candidate for system package managers_
Order of precedence for package installation: Order of precedence for package installation:
1. System package manager (dnf, apt, homebrew, etc.) 1. System package manager (dnf, apt, homebrew, etc.)
2. Source built - only in some situations, like for fast moving software (neovim, hyprland) 2. Source built - only in some situations, like for fast moving software (neovim, hyprland)
3. Appimage (Linux only) - Includes language package managers like `go install`, `cargo install`, and `npm install`
4. Flatpak (Linux only) 3. Flatpak (Linux only)
5. Snap (Linux only), takes precedence over flatpak on Ubuntu based systems 4. Snap (Linux only)
6. Language package manager (`cargo install`, `go install`, `npm install`, etc.) 5. Appimage (Linux only)
_This does not configure installed software, just installs it_ _This does not configure installed software, just installs it_
@@ -26,11 +29,11 @@ To install any of the available packages, they must be part of a list called
## Supported Operating Systems ## Supported Operating Systems
- Fedora Linux - Fedora Linux _first class support_
- MacOS - MacOS _best effort_
- RHEL based distributions *Experimental* *best effort* - RHEL based distributions _Experimental, best effort_
- Debian *Experimental* - Debian _Experimental, best effort_
- Alpine linux *Experimental* *best effort) - Alpine linux _Experimental, best effort_
## Available Packages ## Available Packages

View File

@@ -0,0 +1,22 @@
# vim: set filetype=yaml.ansible :
# Helper: external repository
---
- name: Add copr repository
when:
- ansible_os_family == 'RedHat'
community.general.copr:
host: "{{ repo.host | default('copr.fedorainfracloud.org') }}"
state: "{{ repo.state | default('enabled') }}"
name: "@{{ repo.name }}"
include: "{{ repo.include | default(omit) }}"
exclude: "{{ repo.exclude | default(omit) }}"
- name: Add apt ppa
when:
- ansible_os_family == 'Debian'
ansible.builtin.apt_repository:
codename: "{{ repo.codename | default(omit) }}"
filename: "{{ repo.filename | default(omit) }}"
install_python_apt: true
repo: "{{ repo.name }}"
state: "{{ repo.state | default('present') }}"

View File

@@ -1,26 +1,33 @@
# vim: set filetype=yaml.ansible : # vim: set filetype=yaml.ansible :
--- ---
- name: Install appimage {{ pkg }} - name: Install appimage {{ pkg }}
become: "{{ ext_become }}" become: "{{ install_become }}"
become_user: "{{ install_become_user }}"
block: block:
- name: Ensure appimage path exists - name: Ensure appimage path exists
ansible.builtin.file: ansible.builtin.file:
path: "{{ path.appimage }}/{{ appimage_link_name }}" path: "{{ path_appimage }}/{{ pkg.name }}"
mode: '0755' mode: "{{ pkg.mode | default('0755') }}"
owner: "{{ pkg.owner | default(ansible_user_id) }}"
group: "{{ pkg.group | default(ansible_user_gid) }}"
state: directory state: directory
- name: Fetch appimage - name: Fetch appimage
become: "{{ ext_become }}" become: "{{ install_become }}"
become_user: "{{ install_become_user }}"
ansible.builtin.get_url: ansible.builtin.get_url:
mode: '0755' mode: "{{ pkg.mode | default('0755') }}"
owner: "{{ pkg.owner | default(ansible_user_id) }}"
group: "{{ pkg.group | default(ansible_user_gid) }}"
url: "{{ pkg.url }}"
dest: "{{ path_appimage }}/{{ pkg.name }}/{{ pkg.filename }}"
decompress: false decompress: false
backup: true backup: false
url: "{{ appimage_url }}"
dest: "{{ path.appimage }}/{{ appimage_link_name }}/{{ appimage_file }}"
- name: Link appimage to bin - name: Link appimage to bin
become: "{{ ext_become }}" become: "{{ install_become }}"
become_user: "{{ install_become_user }}"
ansible.builtin.file: ansible.builtin.file:
state: link state: link
src: "{{ path.appimage }}/{{ appimage_link_name }}/{{ appimage_file }}" src: "{{ path_appimage }}/{{ pkg.name }}/{{ pkg.filename }}"
path: "{{ path.bindir }}/{{ appimage_link_name }}" path: "{{ path_bin }}/{{ pkg.name }}"

View File

@@ -1,38 +1,44 @@
# vim: set filetype=yaml.ansible : # vim: set filetype=yaml.ansible :
--- ---
- name: Extract archive to given path - name: Ensure requirements met
when:
- pkg.extract_to is defined
- pkg.name is defined
- pkg.url is defined
block:
- name: Extract archive to given path
block: block:
- name: Ensure directory exists - name: Ensure directory exists
become: "{{ install_become }}" become: "{{ install_become }}"
become_user: "{{ install_become_user }}" become_user: "{{ install_become_user }}"
ansible.bulitin.file: ansible.bulitin.file:
state: directory state: directory
path: "{{ pkg.extract_path }}" path: "{{ pkg.extract_to }}"
mode: "{{ pkg.install_prefix_mode | default('0755') }}" mode: "{{ pkg.mode | default('0755') }}"
owner: "{{ pkg.install_prefix_owner | default(ansible_user_id)}}" owner: "{{ pkg.owner | default(ansible_user_id)}}"
group: "{{ pkg.install_prefix_group | default(ansible_user_gid) }}" group: "{{ pkg.group | default(ansible_user_gid) }}"
- name: Download archive to cache - name: Download archive to cache
ansible.builtin.get_url: ansible.builtin.get_url:
dest: "{{ d_cache }}/{{ pkg.archive_name }}" dest: "{{ d_cache }}/{{ pkg.name }}"
url: "{{ pkg.archive_url }}" url: "{{ pkg.url }}"
checksum: "{{ pkg.archive_checksum | default(omit) }}" checksum: "{{ pkg.checksum | default(omit) }}"
decompress: false decompress: false
mode: '0644' mode: '0644'
- name: Extract archive - name: Extract archive
ansible.builtin.unarchive: ansible.builtin.unarchive:
dest: "{{ pkg.extract_path }}" dest: "{{ pkg.extract_to }}"
src: "{{ d_cache }}/{{ pkg.archive_name }}" src: "{{ d_cache }}/{{ pkg.name }}"
remote_src: true remote_src: true
include: "{{ pkg.archive_include | default(omit) }}" include: "{{ pkg.include | default(omit) }}"
exclude: "{{ pkg.archive_exclude | default(omit) }}" exclude: "{{ pkg.exclude | default(omit) }}"
- name: Symlink archive files - name: Symlink archive files
when: when:
- pkg.link_bin is defined - pkg.bins is defined
- pkg.link_bin | length > 0 - pkg.bins | length > 0
loop: pkg.link_bin loop: pkg.bins
loop_control: loop_control:
loop_var: lnk loop_var: lnk
ansible.builtin.file: ansible.builtin.file:

View File

@@ -1,11 +1,10 @@
# vim: set filetype=yaml.ansible # vim: set filetype=yaml.ansible
--- ---
- name: Install cargo {{ pkg }} - name: Install cargo
become: "{{ ext_become }}" become: "{{ install_become }}"
environment: become_user: "{{ install_become_user }}"
RUSTONIG_SYSTEM_LIBONIG: 1
community.general.cargo: community.general.cargo:
name: "{{ pkg.name | default(pkg) }}" name: "{{ pkg.name | default(pkg) }}"
version: "{{ pkg.vers | default(omit) }}" version: "{{ pkg.version | default(omit) }}"
path: "{{ path.cargo | default(path.prefix) }}" locked: "{{ pkg.locked | default(false) }}"
locked: "{{ pkg.locked | default(omit) }}" path: "{{ install_prefix }}"

View File

@@ -4,11 +4,11 @@
block: block:
- name: Set build variables - name: Set build variables
ansible.builtin.set_fact: ansible.builtin.set_fact:
git_path: "{{ d_tempdir.path }}/{{ name }}" git_path: "{{ d_tempdir.path }}/{{ pkg.name }}"
git_repo: "{{ repo }}" git_repo: "{{ pkg.repo }}"
git_depth: "{{ depth | default(1) }}" git_depth: "{{ pkg.depth | default(1) }}"
git_recursive: "{{ recursive | default(true) }}" git_recursive: "{{ pkg.recursive | default(true) }}"
git_version: "{{ version | default(omit) }}" git_version: "{{ pkg.version | default(omit) }}"
- name: Fetch git repo - name: Fetch git repo
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
@@ -16,9 +16,9 @@
- name: Build cargo release - name: Build cargo release
ansible.builtin.command: ansible.builtin.command:
creates: "{{ bin_output }}" creates: "{{ pkg.bin_output }}"
chdir: "{{ git_path }}" chdir: "{{ pkg.path }}"
argv: "{{ [cargo, build] + cargo_build_flags }}" argv: "{{ [cargo, build] + pkg.build_flags }}"
- name: Install cargo release - name: Install cargo release
block: block:

View File

@@ -2,9 +2,9 @@
--- ---
- name: Clone git repository - name: Clone git repository
ansible.builtin.git: ansible.builtin.git:
depth: "{{ git_depth | default(1) }}" depth: "{{ git.depth | default(1) }}"
dest: "{{ git_path }}" dest: "{{ git.path }}"
force: "{{ git_force | default(true) }}" force: "{{ git.force | default(true) }}"
recursive: "{{ git_recursive | default(true) }}" recursive: "{{ git.recursive | default(true) }}"
repo: "{{ git_repo }}" repo: "{{ git.repo }}"
version: "{{ git_version | default(omit) }}" version: "{{ git.version | default(omit) }}"

View File

@@ -1,8 +1,10 @@
# vim: set filetype=yaml.ansible : # vim: set filetype=yaml.ansible :
--- ---
- name: Install npm {{ pkg }} - name: Install npm
become: true become: "{{ install_become }}"
become_user: "{{ install_become_user }}"
community.general.npm: community.general.npm:
global: true global: "{{ pkg.global | default(true) }}"
name: "{{ pkg }}" name: "{{ pkg.name }}"
state: present version: "{{ pkg.version | default('latest') }}"
state: "{{ pkg.state | default('present') }}"

View File

@@ -1,8 +1,14 @@
# vim: set filetype=yaml.ansible : # vim: set filetype=yaml.ansible :
# Package: air
# Description: application auto reload for go
# Version: latest
# Methods: source (go install)
# Helpers: go_install
--- ---
- name: Configure air # {{{ # {{{ Configure air
- name: Start air configuration
when: when:
- __air_configured is undefined - "'air' not in __configured"
block: block:
- name: Set air install method - name: Set air install method
when: when:
@@ -44,6 +50,6 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
pkg_go: "{{ pkg_go + [air_go_pkg] }}" pkg_go: "{{ pkg_go + [air_go_pkg] }}"
- name: Complete air configuration - name: Finalize air configuration
ansible.builtin.set_fact: ansible.builtin.set_fact:
__air_configured: true __configured: "{{ __configured | combine( { 'air': true } ) }}"

View File

@@ -1,9 +1,5 @@
# vim: set filetype=yaml.ansible : # vim: set filetype=yaml.ansible :
--- ---
- name: Set maintainer
ansible.builtin.set_fact:
ansible_maintainers:
- Matthew Stobbs
- name: Configure ansible - name: Configure ansible
when: when:
- __ansible_configured is undefined or - __ansible_configured is undefined or

View File

@@ -1,6 +1,6 @@
# vim: set filetype=yaml.ansible : # vim: set filetype=yaml.ansible :
--- ---
- name: Add ansible_ls - name: Configure ansible_ls
when: when:
- __ansible_ls_configured is undefined - __ansible_ls_configured is undefined
block: block:
@@ -10,9 +10,19 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
ansible_ls_install_method: "{% if install_method in ansible_ls_install_methods %}{{ install_method }}{% else %}{{ ansible_ls_install_methods[0] }}{% endif %}" ansible_ls_install_method: "{% if install_method in ansible_ls_install_methods %}{{ install_method }}{% else %}{{ ansible_ls_install_methods[0] }}{% endif %}"
- name: Append ansible-language-server to pkg_npm - name: Configure ansible_ls source npm installation
when:
- ansible_ls_install_method == 'source'
ansible.builtin.set_fact: ansible.builtin.set_fact:
pkg_npm: "{{ pkg_npm + ['@ansible/ansible-language-server'] }}" ansible_npm_pkg:
name: '@ansible/ansible-language-server'
global: true
- name: Append ansible-language-server to pkg_npm
when:
- ansible_ls_install_method == 'source'
ansible.builtin.set_fact:
pkg_npm: "{{ pkg_npm + [ansible_npm_pkg] }}"
- name: Set ansible_ls_configured - name: Set ansible_ls_configured
when: when:

View File

@@ -56,11 +56,11 @@
- name: Finalize go archive install - name: Finalize go archive install
ansible.builtin.set_fact: ansible.builtin.set_fact:
go_archive_install: go_archive_install:
extract_path: "{{ go_extract_path }}" extract_to: "{{ go_extract_path }}"
archive_url: "{{ go_archive_url }}" url: "{{ go_archive_url }}"
archive_name: "{{ go_archive }}" name: "{{ go_archive }}"
archive_checksum: "{{ go_archive_sums[go_archive_version][ansible_system][go_arch] }}" checksum: "{{ go_archive_sums[go_archive_version][ansible_system][go_arch] }}"
link_bin: bins:
- from: "{{ go_archive_path }}/go" - from: "{{ go_archive_path }}/go"
to: "{{ path_go }}" to: "{{ path_go }}"
force: true force: true

View File

@@ -37,20 +37,21 @@ path_lib: "{{ install_prefix }}/lib"
# System paths # System paths
# empty lists that must be defined # empty lists that must be defined
pkg_appimage: [] # appimages to install
pkg_archive: [] # packages installed via prebuilt archive pkg_archive: [] # packages installed via prebuilt archive
pkg_cargo: [] # rust packages from cargo using `cargo install` pkg_cargo: [] # rust packages from cargo using `cargo install`
pkg_cargo_build: [] # rust packages using `cargo build` before install pkg_cargo_build: [] # rust packages using `cargo build` before install
pkg_flatpak: [] # flatpak packages to install
pkg_go: [] # go applications pkg_go: [] # go applications
pkg_npm: [] # npm commands pkg_npm: [] # npm commands
pkg_pipx: [] # pipx packages pkg_pipx: [] # pipx packages
pkg_sys_pip: [] # system pip packages pkg_sh: [] # use shell commands to install a package
pkg_snap: [] # snpacraft.io packages
pkg_src: [] # packages built from source pkg_src: [] # packages built from source
pkg_sys: [] # system package manager packages pkg_sys: [] # system package manager packages
pkg_sys_pip: [] # system pip packages
pkg_zig: [] # zig packages pkg_zig: [] # zig packages
pkg_sh: [] # use shell commands to install a package __configured: [] # list of configured packages
pkg_appimage: [] # appimages to install
pkg_flatpak: [] # flatpak packages to install
pkg_snap: [] # snpacraft.io packages
# Per package variables # Per package variables
## {{{ air ## {{{ air