diff --git a/README.md b/README.md index 4e14c89..be415e5 100644 --- a/README.md +++ b/README.md @@ -39,18 +39,25 @@ The `install.sh` script performs the following actions: ### What does the Ansible playbook do? #### The Ansible playbook installs a variety of applications and performs some customizations to the MacOS or Debian environment. Here's a brief overview: -1. Taps into several Homebrew repositories, including HashiCorp, AWS, and Homebrew's own font cask. +1. Taps into several Homebrew repositories, including HashiCorp, AWS, and Twilio. +2. Trusts the HashiCorp and Twilio taps, which Homebrew requires before it loads a non-official tap. #### For MacOS: - Installs a variety of Homebrew packages, including `neovim`, `tmux`, `git-extras`, `thefuck`, `go`, `kubectl`, `skaffold`, `awscli`, `terraform`, `packer`, `aws-sam-cli`, `node`, `redis`, and `molecule`. -- Installs several Homebrew cask packages, including `arc`, `iterm2`, `visual-studio-code`, `1password`, `rectangle`, `font-hack-nerd-font`, `jetbrains-toolbox`, `nordvpn`, `switchresx`, `discord`, `istat-menus`, `signal`, `podman`, `bruno`, `gimp`, `obs`, and `krisp`. +- Installs Homebrew casks selected by profile: + +| Profile | Casks | +|---------|-------| +| Lightweight | `arc`, `iterm2`, `1password`, `rectangle`, `istat-menus` | +| Developer | the lightweight casks, plus `visual-studio-code`, `font-hack-nerd-font`, `jetbrains-toolbox`, `switchresx`, `bruno`, `obs`, `ghostty` | +| Home | the developer casks, plus `nordvpn`, `discord`, `signal`, `gimp`, `krisp` | #### For Debian: - Installs a variety of packages using the package manager, including `neovim`, `tmux`, `git-extras`, `thefuck`, `go`, `kubectl`, `skaffold`, `awscli`, `terraform`, `packer`, `aws-sam-cli`, `node`, `redis`, and `molecule`. -2. Creates directories at `~/stuffy`, `~/stuffy/code`, and `~/stuffy/playground`. +3. Creates directories at `~/stuffy`, `~/stuffy/code`, and `~/stuffy/playground`. ## Notes diff --git a/defilan-osconfig/requirements.yml b/defilan-osconfig/requirements.yml index 3c194cf..c5f39a0 100644 --- a/defilan-osconfig/requirements.yml +++ b/defilan-osconfig/requirements.yml @@ -1,4 +1,4 @@ --- collections: - name: community.general - version: ">=8.0.0" + version: ">=13.3.0" diff --git a/defilan-osconfig/roles/defilan-osconfig/README.md b/defilan-osconfig/roles/defilan-osconfig/README.md index 65db92b..2bfb700 100644 --- a/defilan-osconfig/roles/defilan-osconfig/README.md +++ b/defilan-osconfig/roles/defilan-osconfig/README.md @@ -9,7 +9,7 @@ This role supports three configuration profiles, selected via the `config` varia | Profile | Description | |---------|-------------| | `lightweight` | Essentials only -- basic cask apps (Arc, iTerm2, 1Password, Rectangle, iStat Menus) | -| `developer` | Full developer setup -- CLI tools, languages, containers, and dev-focused cask apps | +| `developer` | Full developer setup -- CLI tools, languages, containers, and dev-focused cask apps (including Ghostty) | | `home` | Productivity/full config -- everything in developer plus personal apps (NordVPN, Discord, Signal, GIMP, Krisp) | ## Requirements diff --git a/defilan-osconfig/roles/defilan-osconfig/tasks/darwin.yml b/defilan-osconfig/roles/defilan-osconfig/tasks/darwin.yml index b38f59e..4a57f32 100644 --- a/defilan-osconfig/roles/defilan-osconfig/tasks/darwin.yml +++ b/defilan-osconfig/roles/defilan-osconfig/tasks/darwin.yml @@ -10,6 +10,16 @@ - packages - homebrew +- name: Trust non-official Homebrew taps + community.general.homebrew_tap: + name: "{{ item }}" + trust: true + loop: "{{ config_packages[config].trusted_taps }}" + when: config_packages[config].trusted_taps is defined + tags: + - packages + - homebrew + - name: Install brew packages community.general.homebrew: name: "{{ config_packages[config].homebrew_packages }}" diff --git a/defilan-osconfig/roles/defilan-osconfig/vars/main.yml b/defilan-osconfig/roles/defilan-osconfig/vars/main.yml index 5426797..c062381 100644 --- a/defilan-osconfig/roles/defilan-osconfig/vars/main.yml +++ b/defilan-osconfig/roles/defilan-osconfig/vars/main.yml @@ -8,6 +8,10 @@ _shared_homebrew_taps: &shared_taps - aws/tap - twilio/brew +_shared_trusted_taps: &shared_trusted_taps + - hashicorp/tap + - twilio/brew + _shared_homebrew_packages: &shared_homebrew - neovim - tmux @@ -50,6 +54,7 @@ config_packages: - istat-menus developer: homebrew_taps: *shared_taps + trusted_taps: *shared_trusted_taps homebrew_packages: *shared_homebrew homebrew_cask_packages: - arc @@ -63,10 +68,11 @@ config_packages: - istat-menus - bruno - obs - - cursor + - ghostty apt_packages: *shared_apt home: homebrew_taps: *shared_taps + trusted_taps: *shared_trusted_taps homebrew_packages: *shared_homebrew homebrew_cask_packages: - arc @@ -85,7 +91,7 @@ config_packages: - gimp - obs - krisp - - cursor + - ghostty apt_packages: *shared_apt defilan_directories: diff --git a/defilan-osconfig/tests/assert-package-lists.yml b/defilan-osconfig/tests/assert-package-lists.yml new file mode 100644 index 0000000..67546da --- /dev/null +++ b/defilan-osconfig/tests/assert-package-lists.yml @@ -0,0 +1,106 @@ +--- +# Asserts the package lists in roles/defilan-osconfig/vars/main.yml and the +# Homebrew trust task in roles/defilan-osconfig/tasks/darwin.yml. +# Run from the defilan-osconfig directory: +# ansible-playbook tests/assert-package-lists.yml +- name: Package list assertions + hosts: localhost + connection: local + gather_facts: false + vars_files: + - ../roles/defilan-osconfig/vars/main.yml + tasks: + - name: Trusted taps are HashiCorp and Twilio only + ansible.builtin.assert: + that: + - config_packages.developer.trusted_taps | default([]) | sort == ['hashicorp/tap', 'twilio/brew'] + - config_packages.home.trusted_taps | default([]) | sort == ['hashicorp/tap', 'twilio/brew'] + fail_msg: "trusted_taps: developer={{ config_packages.developer.trusted_taps | default('MISSING') }} home={{ config_packages.home.trusted_taps | default('MISSING') }}" + tags: [taps] + + - name: Lightweight profile has no trusted taps + ansible.builtin.assert: + that: + - config_packages.lightweight.trusted_taps is not defined + fail_msg: "lightweight has trusted_taps={{ config_packages.lightweight.trusted_taps | default('MISSING') }}" + tags: [taps] + + - name: Ghostty is a cask for developer and home + ansible.builtin.assert: + that: + - "'ghostty' in config_packages.developer.homebrew_cask_packages" + - "'ghostty' in config_packages.home.homebrew_cask_packages" + tags: [casks] + + - name: Cursor is a cask for neither developer nor home + ansible.builtin.assert: + that: + - "'cursor' not in config_packages.developer.homebrew_cask_packages" + - "'cursor' not in config_packages.home.homebrew_cask_packages" + tags: [casks] + + - name: Lightweight profile casks are unchanged + ansible.builtin.assert: + that: + - config_packages.lightweight.homebrew_cask_packages == ['arc', 'iterm2', '1password', 'rectangle', 'istat-menus'] + tags: [parity] + + - name: Shared Homebrew formulae are unchanged + ansible.builtin.assert: + that: + - config_packages.developer.homebrew_packages | sort == expected_formulae + vars: + expected_formulae: + - aws-sam-cli + - awscli + - battery + - exercism + - git-extras + - go + - hashicorp/tap/packer + - hashicorp/tap/terraform + - helm + - kubectl + - kubectx + - minikube + - molecule + - neovim + - node + - podman + - redis + - skaffold + - thefuck + - tmux + - twilio + - yarn + tags: [parity] + +- name: Darwin task file trusts each tap it lists + hosts: localhost + connection: local + gather_facts: false + tasks: + - name: Read the darwin and main task files + vars: + darwin_file: "{{ playbook_dir }}/../roles/defilan-osconfig/tasks/darwin.yml" + ansible.builtin.set_fact: + darwin_tasks_raw: "{{ (lookup('ansible.builtin.file', darwin_file) | from_yaml) | selectattr('name', 'match', '^Trust ') | list }}" + main_tasks: "{{ lookup('ansible.builtin.file', playbook_dir ~ '/../roles/defilan-osconfig/tasks/main.yml') | from_yaml }}" + + - name: Homebrew trust runs on darwin only + ansible.builtin.assert: + that: + - (main_tasks | map('dict2items') + | map('selectattr', 'key', 'equalto', 'ansible.builtin.import_tasks') + | map('map', attribute='value') | flatten + | select('equalto', 'darwin.yml') | list | length) == 1 + + - name: There is one trust task, looping over trusted_taps with trust true + ansible.builtin.assert: + that: + - darwin_tasks_raw | length == 1 + - (darwin_tasks_raw | first)['community.general.homebrew_tap'].trust + - "'trusted_taps' in ((darwin_tasks_raw | first).loop | default(''))" + - ((darwin_tasks_raw | first).when | default('')) == when_trusted_taps_defined + vars: + when_trusted_taps_defined: "config_packages[config].trusted_taps is defined"