Repository: geerlingguy/ansible-collection-mac
Branch: master
Commit: 6ddb5c4cb1ea
Files: 32
Total size: 40.1 KB
Directory structure:
gitextract_x5j9spe2/
├── .ansible-lint
├── .github/
│ ├── FUNDING.yml
│ ├── stale.yml
│ └── workflows/
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── .yamllint
├── LICENSE
├── README.md
├── galaxy-deploy.yml
├── galaxy.yml
├── meta/
│ └── runtime.yml
├── plugins/
│ └── README.md
├── roles/
│ ├── dock/
│ │ ├── README.md
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ └── tasks/
│ │ ├── dock-add.yml
│ │ ├── dock-position.yml
│ │ ├── dock-remove.yml
│ │ └── main.yml
│ ├── homebrew/
│ │ ├── README.md
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ └── vars/
│ │ └── main.yml
│ └── mas/
│ ├── README.md
│ ├── defaults/
│ │ └── main.yml
│ └── tasks/
│ └── main.yml
└── tests/
├── ansible.cfg
├── inventory
├── requirements.yml
├── test.yml
└── uninstall-homebrew.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .ansible-lint
================================================
---
exclude_paths:
- galaxy-deploy.yml
- .ansible/roles/*
skip_list:
- risky-file-permissions
- yaml
- fqcn-builtins
- fqcn[action]
- name[template]
- var-naming[no-role-prefix]
- no-changed-when
- galaxy[no-changelog]
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
---
github: geerlingguy
patreon: geerlingguy
================================================
FILE: .github/stale.yml
================================================
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 90
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- bug
- pinned
- security
- planned
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
pulls:
markComment: |-
This pull request has been marked 'stale' due to lack of recent activity. If there is no further activity, the PR will be closed in another 30 days. Thank you for your contribution!
Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark pull requests as stale.
unmarkComment: >-
This pull request is no longer marked for closure.
closeComment: >-
This pull request has been closed due to inactivity. If you feel this is in error, please reopen the pull request or file a new PR with the relevant details.
issues:
markComment: |-
This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution!
Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale.
unmarkComment: >-
This issue is no longer marked for closure.
closeComment: >-
This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details.
================================================
FILE: .github/workflows/ci.yml
================================================
---
name: CI
'on':
pull_request:
push:
branches:
- master
schedule:
- cron: "0 5 * * 0"
defaults:
run:
working-directory: ansible_collections/geerlingguy/mac
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Check out the codebase.
uses: actions/checkout@v4
with:
path: ansible_collections/geerlingguy/mac
- name: Set up Python 3.
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install test dependencies.
run: pip3 install yamllint ansible-core ansible-lint
- name: Lint code.
run: |
yamllint .
ansible-lint
integration:
name: Integration
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- macos-latest
steps:
- name: Check out the codebase.
uses: actions/checkout@v4
with:
path: ansible_collections/geerlingguy/mac
- name: Uninstall GitHub Actions' built-in Homebrew.
run: tests/uninstall-homebrew.sh
- name: Uninstall GitHub Actions' built-in browser installs.
run: |
sudo rm -rf /Applications/Firefox.app
sudo rm -rf /Applications/Google\ Chrome.app
- name: Install test dependencies.
run: |
sudo pip3 install --upgrade pip
sudo pip3 install ansible-core
- name: Set up the test environment.
run: |
cp tests/ansible.cfg ./ansible.cfg
cp tests/inventory ./inventory
ansible-galaxy collection install community.general
ansible-galaxy role install elliotweiser.osx-command-line-tools
- name: Test the playbook's syntax.
run: ansible-playbook tests/test.yml --syntax-check
- name: Test the playbook.
run: ansible-playbook tests/test.yml
env:
ANSIBLE_FORCE_COLOR: '1'
- name: Idempotence check.
run: |
idempotence=$(mktemp)
ansible-playbook tests/test.yml | tee -a ${idempotence}
tail ${idempotence} | grep -q 'changed=0.*failed=0' && (echo 'Idempotence test: pass' && exit 0) || (echo 'Idempotence test: fail' && exit 1)
env:
ANSIBLE_FORCE_COLOR: '1'
================================================
FILE: .github/workflows/release.yml
================================================
---
name: Release
'on':
push:
tags:
- '*'
defaults:
run:
working-directory: ansible_collections/geerlingguy/mac
jobs:
release:
name: Release
runs-on: ubuntu-latest
env:
ANSIBLE_GALAXY_TOKEN: ${{ secrets.ANSIBLE_GALAXY_TOKEN }}
ANSIBLE_FORCE_COLOR: 1
steps:
- name: Check out the codebase.
uses: actions/checkout@v2
with:
path: ansible_collections/geerlingguy/mac
- name: Set up Python 3.
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install Ansible.
run: pip3 install ansible-core
- name: Release to Ansible Galaxy.
run: ansible-playbook -i 'localhost,' galaxy-deploy.yml -e "github_tag=${{ github.ref }}"
================================================
FILE: .gitignore
================================================
roles/.DS_Store
================================================
FILE: .yamllint
================================================
---
extends: default
rules:
line-length:
max: 180
level: warning
comments:
min-spaces-from-content: 1
comments-indentation: false
braces:
min-spaces-inside: 0
max-spaces-inside: 1
octal-values:
forbid-implicit-octal: true
forbid-explicit-octal: true
ignore: |
.github/stale.yml
================================================
FILE: LICENSE
================================================
Copyright 2021 Jeff Geerling
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# Mac Collection for Ansible
[![MIT licensed][badge-license]][link-license]
[![Galaxy Collection][badge-collection]][link-galaxy]
[![CI][badge-gh-actions]][link-gh-actions]
This collection includes helpful Ansible roles and content to help with macOS automation. For a good example of the collection's usage, see the [Mac Dev Playbook](https://github.com/geerlingguy/mac-dev-playbook).
Roles included in this collection (click on the link to see the role's README and documentation):
- `geerlingguy.mac.homebrew` ([documentation](https://github.com/geerlingguy/ansible-collection-mac/blob/master/roles/homebrew/README.md))
- `geerlingguy.mac.mas` ([documentation](https://github.com/geerlingguy/ansible-collection-mac/blob/master/roles/mas/README.md))
- `geerlingguy.mac.dock` ([documentation](https://github.com/geerlingguy/ansible-collection-mac/blob/master/roles/dock/README.md))
## Installation
Install via Ansible Galaxy:
```
ansible-galaxy collection install geerlingguy.mac
```
Or include this collection in your playbook's `requirements.yml` file:
```
---
collections:
- name: geerlingguy.mac
```
For a real-world example, see my [Mac Dev Playbook's requirements file](https://github.com/geerlingguy/mac-dev-playbook/blob/master/requirements.yml).
### Role Requirements
Requires separate installation of the `elliotweiser.osx-command-line-tools` role. Because Ansible collections are not able to depend on roles, you will need to make sure that role is installed either by manually installing it with the `ansible-galaxy` command, or adding it under the `roles` section of your `requirements.yml` file:
```yaml
---
roles:
- name: elliotweiser.osx-command-line-tools
collections:
- name: geerlingguy.mac
```
## Usage
Here's an example playbook which installs some Mac Apps (assuming you are signed into the App Store), CLI tools via Homebrew, and Cask Apps using Homebrew:
```yaml
- hosts: localhost
connection: local
gather_facts: false
vars:
mas_installed_app_ids:
- 424389933 # Final Cut Pro
- 497799835 # Xcode
homebrew_installed_packages:
- node
- nvm
- redis
- ssh-copy-id
- pv
homebrew_cask_apps:
- docker
- firefox
- google-chrome
- vlc
roles:
- geerlingguy.mac.homebrew
- geerlingguy.mac.mas
```
For a real-world usage example, see my [Mac Dev Playbook](https://github.com/geerlingguy/mac-dev-playbook).
See the full documentation for each role in the role's README, linked above.
## License
MIT
## Author
This collection was created by [Jeff Geerling](https://www.jeffgeerling.com), author of [Ansible for DevOps](https://www.ansiblefordevops.com).
[badge-gh-actions]: https://github.com/geerlingguy/ansible-collection-mac/workflows/CI/badge.svg?event=push
[link-gh-actions]: https://github.com/geerlingguy/ansible-collection-mac/actions?query=workflow%3ACI
[badge-collection]: https://img.shields.io/badge/collection-geerlingguy.mac-blue
[link-galaxy]: https://galaxy.ansible.com/geerlingguy/mac
[badge-license]: https://img.shields.io/github/license/geerlingguy/ansible-collection-mac.svg
[link-license]: https://github.com/geerlingguy/ansible-collection-mac/blob/master/LICENSE
[badge-gh-actions]: https://github.com/geerlingguy/ansible-role-homebrew/workflows/CI/badge.svg?event=push
================================================
FILE: galaxy-deploy.yml
================================================
---
# Automated release playbook for Ansible Collections.
#
# Originally based on Ericsysmin's 2020 blog post. Meant to be used in a GitHub
# Actions CI environment.
#
# Requires a ANSIBLE_GALAXY_TOKEN secret to be configured on the GitHub repo.
#
# Usage:
# ansible-playbook -i 'localhost,' galaxy-deploy.yml \
# -e "github_tag=${{ github.ref }}"
- name: Deploy new Collection version to Galaxy.
hosts: localhost
connection: local
gather_facts: false
vars:
namespace: geerlingguy
collection: mac
# Requires github_tag to be set when calling playbook.
release_tag: "{{ github_tag.split('/')[-1] }}"
pre_tasks:
- name: Ensure ANSIBLE_GALAXY_TOKEN is set.
fail:
msg: A valid ANSIBLE_GALAXY_TOKEN must be set.
when: "lookup('env', 'ANSIBLE_GALAXY_TOKEN') | length == 0"
- name: Ensure the ~/.ansible directory exists.
file:
path: ~/.ansible
state: directory
- name: Write the Galaxy token to ~/.ansible/galaxy_token
copy:
content: |
token: {{ lookup('env', 'ANSIBLE_GALAXY_TOKEN') }}
dest: ~/.ansible/galaxy_token
tasks:
- name: Ensure the galaxy.yml tag is up to date.
lineinfile:
path: galaxy.yml
regexp: "^version:"
line: 'version: "{{ release_tag }}"'
- name: Build the collection.
command: ansible-galaxy collection build
changed_when: true
- name: Publish the collection.
command: >
ansible-galaxy collection publish ./{{ namespace }}-{{ collection }}-{{ release_tag }}.tar.gz
changed_when: true
================================================
FILE: galaxy.yml
================================================
---
namespace: geerlingguy
name: mac
version: "1.2.0"
readme: README.md
authors:
- geerlingguy
description: Collection of macOS automation tools for Ansible.
# Either a single license or a list of licenses for content inside of a collection. Ansible Galaxy currently only
# accepts L(SPDX,https://spdx.org/licenses/) licenses. This key is mutually exclusive with 'license_file'
license:
- MIT
# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character
# requirements as 'namespace' and 'name'
tags:
- mac
- macos
- tools
- osx
- homebrew
- brew
- workstation
- dev
- mas
- appstore
- apps
- configure
- development
- apple
- ios
- macbook
- imac
- macmini
- server
dependencies:
community.general: ">=3.0.0"
repository: https://github.com/geerlingguy/ansible-collection-mac
documentation: https://github.com/geerlingguy/ansible-collection-mac
homepage: https://www.jeffgeerling.com
issues: https://github.com/geerlingguy/ansible-collection-mac/issues
build_ignore: []
================================================
FILE: meta/runtime.yml
================================================
---
requires_ansible: ">=2.15.0"
================================================
FILE: plugins/README.md
================================================
# Collections Plugins Directory
This directory can be used to ship various plugins inside an Ansible collection. Each plugin is placed in a folder that
is named after the type of plugin it is in. It can also include the `module_utils` and `modules` directory that
would contain module utils and modules respectively.
Here is an example directory of the majority of plugins currently supported by Ansible:
```
└── plugins
├── action
├── become
├── cache
├── callback
├── cliconf
├── connection
├── filter
├── httpapi
├── inventory
├── lookup
├── module_utils
├── modules
├── netconf
├── shell
├── strategy
├── terminal
├── test
└── vars
```
A full list of plugin types can be found at [Working With Plugins](https://docs.ansible.com/ansible/2.11/plugins/plugins.html).
================================================
FILE: roles/dock/README.md
================================================
# Ansible Role: macOS Dock Automation
This role automates the use of `dockutil` to manage the items in your macOS Dock. You can add, remove, and arrange Dock items.
## Requirements
- **Homebrew**: Requires `homebrew` already installed (you can use `geerlingguy.mac.homebrew` to install it on your Mac).
## Role Variables
Available variables are listed below, along with example values (see `defaults/main.yml`):
```yaml
dockitems_remove: []
```
Dock items to remove.
```yaml
dockitems_persist: []
```
Dock items to add. `pos` parameter is optional and will place the Dock item in a particular position in the Dock.
```yaml
dockutil_install: true
```
Whether to install dockutil or not. If set to false you'll need to have installed dockutil prior to the execution of this role. See [this issue](https://github.com/geerlingguy/ansible-collection-mac/issues/42) for alternate installation methods, which may be necessary depending on your version of macOS.
## Dependencies
- (Soft dependency) `geerlingguy.homebrew`
## Example Playbook
```yaml
- hosts: localhost
vars:
dockitems_remove:
- Launchpad
- TV
- Podcasts
- 'App Store'
dockitems_persist:
- name: Messages
path: "/Applications/Messages.app/"
- name: Safari
path: "/Applications/Safari.app/"
pos: 2
- name: Sublime Text
path: "/Applications/Sublime Text.app/"
pos: 3
roles:
- geerlingguy.mac.homebrew
- geerlingguy.mac.dock
```
See the [Mac Development Ansible Playbook](https://github.com/geerlingguy/mac-dev-playbook) for an example of this role's usage.
## License
MIT / BSD
## Author Information
This role was created in 2021 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/).
The contents of this role were originally created by [@dspolleke](https://github.com/dspolleke) as part of the [`mac-dev-playbook`](https://github.com/geerlingguy/mac-dev-playbook).
================================================
FILE: roles/dock/defaults/main.yml
================================================
---
# Dock items to remove.
dockitems_remove: []
# - Launchpad
# - TV
# - Podcasts
# - 'App Store'
# Dock items to add. `pos` parameter is optional and will place the Dock item
# in a particular position in the Dock.
dockitems_persist: []
# - name: "Sublime Text"
# path: "/Applications/Sublime Text.app/"
# pos: 5
# Whether to install dockutil or not
dockutil_install: true
================================================
FILE: roles/dock/tasks/dock-add.yml
================================================
---
- name: "See if Dock item {{ item.name | default(item) }} exists."
ansible.builtin.command: "dockutil --find '{{ item.name }}'"
register: dockitem_exists
failed_when: >
"No such file or directory" in dockitem_exists.stdout
or "command not found" in dockitem_exists.stdout
changed_when: false
tags: ['dock']
- name: Get current dock section from output.
set_fact:
current_section: "{{ dockitem_exists.stdout | regex_replace('^.*was found in (.*) at slot.*$', '\\1') }}"
when: dockitem_exists.rc == 0
tags: ['dock']
- name: Ensure Dock item {{ item.name | default(item) }} exists.
ansible.builtin.command: |
dockutil --add '{{ item.path }}' --label '{{ item.name }}'
{% if not ansible_loop.last %}--no-restart{% endif %}
when: dockitem_exists.rc > 0 or
dockitem_exists.rc == 0 and current_section == 'recent-apps'
tags: ['dock']
- name: Pause for 7 seconds between dock changes.
ansible.builtin.pause:
seconds: 7
when:
- dockitem_exists.rc > 0 or
dockitem_exists.rc == 0 and current_section == 'recent-apps'
- ansible_loop.last
tags: ['dock']
================================================
FILE: roles/dock/tasks/dock-position.yml
================================================
---
- name: "Check the current Dock position of {{ item.name | default(item) }}."
ansible.builtin.command:
cmd: dockutil --find '{{ item.name | default(item) }}'
register: dock_item_position
failed_when: '"command not found" in dock_item_position.stdout'
changed_when: false
- name: Get current dock item position from output.
set_fact:
current_position: "{{ dock_item_position | regex_replace('^.*slot (.*) in.*$', '\\1') }}"
- name: Move dock item to the correct position.
ansible.builtin.command:
cmd: |
dockutil --move '{{ item.name | default(item) }}' --position '{{ item.pos }}'
{% if not ansible_loop.last %}--no-restart{% endif %}
when: current_position|int != item.pos|int
================================================
FILE: roles/dock/tasks/dock-remove.yml
================================================
---
- name: "See if {{ item }} is in the Dock."
ansible.builtin.command:
cmd: dockutil --find '{{ item }}'
register: dockitem_exists
changed_when: false
failed_when: >
"No such file or directory" in dockitem_exists.stdout
or "command not found" in dockitem_exists.stdout
tags: ['dock']
- name: Ensure Dock item {{ item }} is removed.
ansible.builtin.command:
cmd: |
dockutil --remove '{{ item }}'
{% if not ansible_loop.last %}--no-restart{% endif %}
when: dockitem_exists.rc == 0
tags: ['dock']
- name: Pause for 7 seconds between dock changes.
ansible.builtin.pause:
seconds: 7
when:
- dockitem_exists.rc == 0
- ansible_loop.last
tags: ['dock']
================================================
FILE: roles/dock/tasks/main.yml
================================================
---
- name: Install dockutil.
community.general.homebrew:
name: dockutil
state: present
notify:
- Clear homebrew cache
when: dockutil_install
tags: ['dock']
- name: Remove configured Dock items.
ansible.builtin.include_tasks: dock-remove.yml
loop: "{{ dockitems_remove }}"
loop_control:
extended: true
extended_allitems: false
tags: ['dock']
- name: Ensure required dock items exist.
ansible.builtin.include_tasks: dock-add.yml
loop: "{{ dockitems_persist }}"
loop_control:
extended: true
extended_allitems: false
tags: ['dock']
- name: Ensure dock items are in correct position.
ansible.builtin.include_tasks: dock-position.yml
when:
- item.pos is defined
- item.pos > 0
loop: "{{ dockitems_persist }}"
loop_control:
extended: true
extended_allitems: false
tags: ['dock']
================================================
FILE: roles/homebrew/README.md
================================================
# Ansible Role: Homebrew
Installs [Homebrew][homebrew] on MacOS, and configures packages, taps, and cask apps according to supplied variables.
## Requirements
None.
## Role Variables
Available variables are listed below, along with default values (see [`defaults/main.yml`](defaults/main.yml)):
homebrew_repo: https://github.com/Homebrew/brew
The GitHub repository for Homebrew core.
homebrew_prefix: "{{ (ansible_facts.machine == 'arm64') | ternary('/opt/homebrew', '/usr/local') }}"
homebrew_install_path: "{{ homebrew_prefix }}{{ '/Homebrew' if ansible_facts.machine != 'arm64' }}"
The path where Homebrew will be installed (`homebrew_prefix` is the parent directory). It is recommended you stick to the default, otherwise Homebrew might have some weird issues. If you change this variable, you should also manually create a symlink back to `/opt/homebrew` (or `/usr/local` if you're on an Intel-mac) so things work as Homebrew expects.
homebrew_brew_bin_path: {{ homebrew_prefix }}/bin
The path where `brew` will be installed.
homebrew_installed_packages:
- ssh-copy-id
- pv
- { name: vim, install_options: "with-luajit,override-system-vi" }
Packages you would like to make sure are installed via `brew install`. You can optionally add flags to the install by setting an `install_options` property, and if used, you need to explicitly set the `name` for the package as well. By default, no packages are installed (`homebrew_installed_packages: []`).
homebrew_uninstalled_packages: []
Packages you would like to make sure are _uninstalled_.
homebrew_upgrade_all_packages: false
Whether to upgrade homebrew and all packages installed by homebrew. If you prefer to manually update packages via `brew` commands, leave this set to `false`.
homebrew_taps:
- { name: my_company/internal_tap, url: 'https://example.com/path/to/tap.git' }
Taps you would like to make sure Homebrew has tapped.
homebrew_cask_apps:
- firefox
- { name: virtualbox, install_options:"debug,appdir=/Applications" }
Apps you would like to have installed via `cask`. [Search][caskroom] for popular apps to see if they're available for install via Cask. Cask will not be used if it is not included in the list of taps in the `homebrew_taps` variable. You can optionally add flags to the install by setting an `install_options` property, and if used, you need to explicitly set the `name` for the package as well. By default, no Cask apps will be installed (`homebrew_cask_apps: []`).
homebrew_cask_accept_external_apps: true
Default value is `false` and would result in interruption of further processing of the whole role (and ansible play) in case any app given in `homebrew_cask_apps` is already installed without `cask`. Good for a tightly managed system.
Specify as `true` instead if you prefer to silently continue if any App is already installed without `cask`. Generally good for a system that is managed with `cask` / `Ansible` as well as other install methods (like manually) at the same time.
homebrew_cask_uninstalled_apps:
- google-chrome
Apps you would like to make sure are _uninstalled_.
homebrew_cask_appdir: /Applications
Directory where applications installed via `cask` should be installed.
ansible_become_password: ""
Set this to your account password if casks you want installed need elevated privileges while installing (like `microsoft-office`), preferably [encrypted via `ansible-vault`][link-vault-doc].
homebrew_use_brewfile: true
Whether to install via a Brewfile. If so, you will need to install the `homebrew/bundle` tap, which could be done within `homebrew_taps`.
homebrew_brewfile_dir: '~'
The directory where your Brewfile is located.
homebrew_clear_cache: false
Set to `true` to remove the Hombrew cache after any new software is installed.
homebrew_user: "{{ ansible_facts.user_id }}"
The user that you would like to install Homebrew as.
homebrew_group: "{{ ansible_facts.user_gid }}"
The group that you would like to use while installing Homebrew.
homebrew_folders_additional: []
Any additional folders inside `homebrew_prefix` for which to ensure homebrew user/group ownership.
## Dependencies
- [elliotweiser.osx-command-line-tools][dep-osx-clt-role]
## Example Playbook
- hosts: localhost
vars:
homebrew_installed_packages:
- mysql
roles:
- geerlingguy.mac.homebrew
See the `tests/local-testing` directory for an example of running this role over
Ansible's `local` connection. See also:
[Mac Development Ansible Playbook][mac-dev-playbook].
## License
[MIT][link-license]
## Author Information
This role was created in 2014 by [Jeff Geerling][author-website], author of
[Ansible for DevOps][ansible-for-devops].
#### Maintainer(s)
- [Jeff Geerling](https://github.com/geerlingguy)
- [Elliot Weiser](https://github.com/elliotweiser)
[ansible-for-devops]: https://www.ansiblefordevops.com/
[author-website]: https://www.jeffgeerling.com/
[caskroom]: https://caskroom.github.io/search
[homebrew]: http://brew.sh/
[dep-osx-clt-role]: https://galaxy.ansible.com/elliotweiser/osx-command-line-tools/
[link-galaxy]: https://galaxy.ansible.com/geerlingguy/homebrew/
[link-license]: https://raw.githubusercontent.com/geerlingguy/ansible-role-homebrew/master/LICENSE
[link-gh-actions]: https://github.com/geerlingguy/ansible-role-homebrew/actions?query=workflow%3ACI
[mac-dev-playbook]: https://github.com/geerlingguy/mac-dev-playbook
[link-vault-doc]: https://docs.ansible.com/ansible/latest/user_guide/vault.html#creating-encrypted-variables
================================================
FILE: roles/homebrew/defaults/main.yml
================================================
---
homebrew_repo: https://github.com/Homebrew/brew
homebrew_prefix: "{{ (ansible_facts.machine == 'arm64') | ternary('/opt/homebrew', '/usr/local') }}"
homebrew_install_path: "{{ homebrew_prefix }}{{ '/Homebrew' if ansible_facts.machine != 'arm64' }}"
homebrew_brew_bin_path: "{{ homebrew_prefix }}/bin"
homebrew_installed_packages: []
homebrew_uninstalled_packages: []
homebrew_upgrade_all_packages: false
homebrew_taps: []
homebrew_cask_apps: []
homebrew_cask_uninstalled_apps: []
homebrew_cask_appdir: /Applications
homebrew_cask_accept_external_apps: false
# Set this to your account password if casks need elevated privileges.
# ansible_become_password: ''
homebrew_use_brewfile: true
homebrew_brewfile_dir: '~'
homebrew_clear_cache: false
homebrew_folders_additional: []
================================================
FILE: roles/homebrew/handlers/main.yml
================================================
---
# handlers for ansible-role-homebrew
- name: Clear homebrew cache
file:
path: "{{ homebrew_cache_path.stdout | trim }}"
state: absent
when: 'homebrew_clear_cache | bool'
become: "{{ (homebrew_user != ansible_facts.user_id) | bool }}"
become_user: "{{ homebrew_user }}"
================================================
FILE: roles/homebrew/tasks/main.yml
================================================
---
- name: Determine Homebrew ownership variables
set_fact:
homebrew_user: '{{ homebrew_user | default(ansible_facts.user_id) }}'
homebrew_group: '{{ homebrew_group | default(ansible_facts.user_gid) }}'
# Homebrew setup prerequisites.
- name: Ensure Homebrew parent directory has correct permissions (Apple Silicon).
file:
path: "{{ homebrew_prefix }}"
owner: "{{ homebrew_user }}"
state: directory
become: true
when: ansible_facts.machine == 'arm64'
- name: Ensure Homebrew parent directory has correct permissions (Intel).
when: ansible_facts.machine == 'x86_64'
block:
- name: Ensure Homebrew parent directory has correct permissions (MacOS >= 10.13).
file:
path: "{{ homebrew_prefix }}"
owner: root
state: directory
become: true
when: "ansible_facts.distribution_version is version('10.13', '>=')"
- name: Ensure Homebrew parent directory has correct permissions (MacOS < 10.13).
file:
path: "{{ homebrew_prefix }}"
owner: root
group: admin
state: directory
mode: "0775"
become: true
when: "ansible_facts.distribution_version is version('10.13', '<')"
- name: Check if homebrew already exists.
stat:
path: "{{ homebrew_brew_bin_path }}/brew"
register: pre_installed_brew
- name: Ensure Homebrew directory exists.
file:
path: "{{ homebrew_install_path }}"
owner: "{{ homebrew_user }}"
group: "{{ homebrew_group }}"
state: directory
mode: "0775"
become: true
# Clone Homebrew.
- name: Ensure Homebrew is installed.
git:
repo: "{{ homebrew_repo }}"
version: master
dest: "{{ homebrew_install_path }}"
update: false
depth: 1
become: true
become_user: "{{ homebrew_user }}"
when: not pre_installed_brew.stat.exists
# Adjust Homebrew permissions.
- name: Ensure proper permissions and ownership on homebrew_brew_bin_path dirs.
file:
path: "{{ homebrew_brew_bin_path }}"
state: directory
owner: "{{ homebrew_user }}"
group: "{{ homebrew_group }}"
mode: "0775"
become: true
- name: Ensure proper ownership on homebrew_install_path subdirs.
file:
path: "{{ homebrew_install_path }}"
state: directory
owner: "{{ homebrew_user }}"
group: "{{ homebrew_group }}"
recurse: true
follow: false
become: true
# Place brew binary in proper location and complete setup.
- name: Check if homebrew binary is already in place.
stat:
path: "{{ homebrew_brew_bin_path }}/brew"
register: homebrew_binary
check_mode: false
- name: Symlink brew to homebrew_brew_bin_path.
file:
src: "{{ homebrew_install_path }}/bin/brew"
dest: "{{ homebrew_brew_bin_path }}/brew"
state: link
when: not homebrew_binary.stat.exists
become: true
- name: Add missing folder if not on Apple-chipset
set_fact:
homebrew_folders_base: "{{ homebrew_folders_base + ['Homebrew'] }}"
when: ansible_facts.machine != 'arm64'
- name: Ensure proper homebrew folders are in place.
file:
path: "{{ homebrew_prefix }}/{{ item }}"
state: directory
owner: "{{ homebrew_user }}"
group: "{{ homebrew_group }}"
become: true
loop: "{{ homebrew_folders_base + homebrew_folders_additional }}"
- name: Collect package manager fact.
setup:
filter: ansible_facts.pkg_mgr
- name: Perform brew installation.
# Privilege escalation is only required for inner steps when
# the `homebrew_user` doesn't match the `ansible_facts.user_id`
become: "{{ (homebrew_user != ansible_facts.user_id) | bool }}"
become_user: "{{ homebrew_user }}"
block:
- name: Force update brew after installation.
command: "{{ homebrew_brew_bin_path }}/brew update --force"
when: not pre_installed_brew.stat.exists
- name: Where is the cache?
command: "{{ homebrew_brew_bin_path }}/brew --cache"
register: homebrew_cache_path
changed_when: false
check_mode: false
# Tap.
- name: Ensure configured taps are tapped.
homebrew_tap:
tap: '{{ item.name | default(item) }}'
url: '{{ item.url | default(omit) }}'
state: present
loop: "{{ homebrew_taps }}"
# Cask.
- name: Ensure blacklisted cask applications are not installed.
homebrew_cask:
name: "{{ item }}"
state: absent
sudo_password: "{{ ansible_become_password | default(omit) }}"
loop: "{{ homebrew_cask_uninstalled_apps }}"
- name: Install configured cask applications.
homebrew_cask:
name: "{{ item.name | default(item) }}"
state: present
install_options: "{{ item.install_options | default('appdir=' + homebrew_cask_appdir) }}"
accept_external_apps: "{{ homebrew_cask_accept_external_apps }}"
sudo_password: "{{ ansible_become_password | default(omit) }}"
loop: "{{ homebrew_cask_apps }}"
notify:
- Clear homebrew cache
# Brew.
- name: Ensure blacklisted homebrew packages are not installed.
homebrew:
name: "{{ item }}"
state: absent
loop: "{{ homebrew_uninstalled_packages }}"
- name: Ensure configured homebrew packages are installed.
homebrew:
path: "{{ homebrew_brew_bin_path }}"
name: "{{ item.name | default(item) }}"
install_options: "{{ item.install_options | default(omit) }}"
state: "{{ item.state | default('present') }}"
loop: "{{ homebrew_installed_packages }}"
notify:
- Clear homebrew cache
- name: Upgrade all homebrew packages (if configured).
homebrew:
update_homebrew: true
upgrade_all: true
when: homebrew_upgrade_all_packages
notify:
- Clear homebrew cache
- name: Check for Brewfile.
stat:
path: "{{ homebrew_brewfile_dir }}/Brewfile"
register: homebrew_brewfile
check_mode: false
- name: Install from Brewfile.
command: "{{ homebrew_brew_bin_path }}/brew bundle"
args:
chdir: "{{ homebrew_brewfile_dir }}"
when: homebrew_brewfile.stat.exists and homebrew_use_brewfile
================================================
FILE: roles/homebrew/vars/main.yml
================================================
---
homebrew_folders_base:
- Cellar
- Frameworks
- Caskroom
- bin
- etc
- include
- lib
- opt
- sbin
- share
- share/zsh
- share/zsh/site-functions
- var
================================================
FILE: roles/mas/README.md
================================================
# Ansible Role: Mac App Store CLI (mas)
Installs [mas](https://github.com/mas-cli/mas) on macOS, and installs macOS apps from the Mac App Store.
## Requirements
- **Homebrew**: Requires `homebrew` already installed (you can use `geerlingguy.mac.homebrew` to install it on your Mac).
- **Mac App Store account**: You can either sign into the Mac App Store via the GUI before running this role, or you can set the `mas_email` and `mas_password` prior to running the role. For security reasons, if you're going to use this role to sign in, you should use `vars_prompt` for at least the password; don't store unencrypted passwords with your playbooks!
## Role Variables
Available variables are listed below, along with default values (see `defaults/main.yml`):
mas_email: ""
mas_password: ""
The credentials for your Mac App Store account. The Apps you install should already be purchased by/registered to this account.
If setting these variables statically (e.g. in an included vars file), you should encrypt the inventory using [Ansible Vault](http://docs.ansible.com/ansible/playbooks_vault.html). Otherwise you can use [`vars_prompt`](http://docs.ansible.com/ansible/playbooks_prompts.html) to prompt for the password at playbook runtime.
If you leave both blank, and don't prompt for them, the role assumes you've already signed in via other means (e.g. via GUI or `mas signin [email]`), and will not attempt to sign in again.
mas_signin_dialog: false
Fallback to the built-in Mac App Store dialog to complete sign in. If set to yes, you must specify the aforementioned `mas_email` variable which will be autofilled in the dialog and prompt you to enter your password, followed by the 2FA authorization code if enabled on the account.
### Install apps
mas_installed_apps:
- { id: 425264550, name: "Blackmagic Disk Speed Test (3.0)" }
- { id: 411643860, name: "DaisyDisk (4.3.2)" }
- { id: 498486288, name: "Quick Resizer (1.9)" }
- { id: 497799835, name: "Xcode (8.1)" }
A list of apps to ensure are installed on the computer using the Mac App Store. You can get IDs for all your existing installed apps with `mas list`, and you can search for IDs with `mas search [App Name]`. The `name` attribute is not authoritative and only used to provide better information in the playbook output.
mas_upgrade_all_apps: false
Whether to run `mas upgrade`, which will upgrade all installed Mac App Store apps.
mas_path: "{{ '/opt/homebrew/bin/mas' if ansible_facts.architecture == 'arm64' else '/usr/local/bin/mas' }}"
When targeting a remote Mac, the PATH isn't always correct leading to the `mas` binary not being found. This variable allows you to override the path to the `mas` binary. The defaults above work for most installations, but you may need to override this if you have a custom Homebrew installation path or other custom setup.
### Remove installed apps
mas_uninstalled_apps:
- { id: 408981434, name: "iMovie" }
- { id: 409183694, name: "Keynote" }
- { id: 409201541, name: "Pages" }
- { id: 409203825, name: "Numbers" }
- { id: 682658836, name: "GarageBand" }
A list of apps to uninstall from the computer, which were installed using the Mac App Store. You can get IDs for all your existing installed apps with `mas list`. The `name` attribute is not authoritative and only used to provide better information in the playbook output.
## Dependencies
- (Soft dependency) `geerlingguy.homebrew`
## Example Playbook
- hosts: localhost
vars:
mas_installed_apps:
- { id: 497799835, name: "Xcode (8.1)" }
roles:
- geerlingguy.mac.homebrew
- geerlingguy.mac.mas
See the [Mac Development Ansible Playbook](https://github.com/geerlingguy/mac-dev-playbook) for an example of this role's usage.
## License
MIT / BSD
## Author Information
This role was created in 2016 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/).
================================================
FILE: roles/mas/defaults/main.yml
================================================
---
mas_email: ""
mas_password: ""
mas_uninstalled_apps: []
mas_installed_app_ids: [] # Deprecated
mas_installed_apps:
- { id: 425264550, name: "Blackmagic Disk Speed Test (3.0)" }
- { id: 411643860, name: "DaisyDisk (4.3.2)" }
- { id: 498486288, name: "Quick Resizer (1.9)" }
- { id: 497799835, name: "Xcode (8.1)" }
mas_upgrade_all_apps: false
mas_signin_dialog: false
mas_path: "{{ '/opt/homebrew/bin/mas' if ansible_facts.architecture == 'arm64' else '/usr/local/bin/mas' }}"
================================================
FILE: roles/mas/tasks/main.yml
================================================
---
- name: Ensure MAS is installed.
homebrew:
name: mas
state: present
- name: Get MAS account status
command: '"{{ mas_path }}" account'
register: mas_account_result
failed_when: mas_account_result.rc > 1
check_mode: false
changed_when: false
when:
- ansible_facts.distribution_version is version('12', '<')
- name: Sign in to MAS when email and password are provided.
command: '"{{ mas_path }}" signin "{{ mas_email }}" "{{ mas_password }}"'
register: mas_signin_result
when:
- ansible_facts.distribution_version is version('10.13', '<')
- mas_account_result.rc == 1
- mas_email is truthy
- mas_password is truthy
- not mas_signin_dialog
- name: Sign in to MAS when email is provided, and complete password and 2FA using dialog.
command: '"{{ mas_path }}" signin "{{ mas_email }}" "{{ mas_password }}" --dialog'
register: mas_signin_result
when:
- ansible_facts.distribution_version is version('10.13', '<')
- mas_signin_dialog
- mas_account_result.rc == 1
- mas_email is truthy
# - name: List installed MAS apps.
# command: '"{{ mas_path }}" list'
# register: mas_list
# check_mode: false
# changed_when: false
# failed_when: mas_list.rc not in [0,1]
- name: Ensure unwanted MAS apps are uninstalled.
become: true
environment:
PATH: "{{ mas_path | dirname }}:{{ ansible_facts.env.PATH }}"
community.general.mas:
id: "{{ item.id | default(item) }}"
state: absent
loop: "{{ mas_uninstalled_apps }}"
loop_control:
label: "{{ item.name | default(item.id | default(item)) }}"
- name: Ensure configured MAS apps are installed.
become: true
environment:
PATH: "{{ mas_path | dirname }}:{{ ansible_facts.env.PATH }}"
community.general.mas:
id: "{{ item.id | default(item) }}"
state: present
loop: "{{ mas_installed_apps + mas_installed_app_ids }}"
loop_control:
label: "{{ item.name | default(item.id | default(item)) }}"
- name: Upgrade all apps (if configured).
become: true
environment:
PATH: "{{ mas_path | dirname }}:{{ ansible_facts.env.PATH }}"
community.general.mas:
upgrade_all: true
when: mas_upgrade_all_apps
================================================
FILE: tests/ansible.cfg
================================================
[defaults]
inventory = inventory
collections_path = ../../../
================================================
FILE: tests/inventory
================================================
[local]
localhost ansible_connection=local
================================================
FILE: tests/requirements.yml
================================================
---
roles:
- name: elliotweiser.osx-command-line-tools
collections:
- name: community.general
================================================
FILE: tests/test.yml
================================================
---
- name: Test the collection.
hosts: localhost
vars:
homebrew_clear_cache: true
homebrew_installed_packages:
- ssh-copy-id # from homebrew/core
- nginx-full # from dengi/nginx
homebrew_cask_apps:
- firefox # from hombrew/cask
- google-chrome # from hombrew/cask
homebrew_taps:
- name: denji/nginx
url: 'https://github.com/denji/homebrew-nginx.git'
mas_uninstalled_apps: []
mas_installed_app_ids: []
mas_installed_apps: []
dockitems_remove:
- Launchpad
- TV
dockitems_persist:
- name: Safari
path: "/Applications/Safari.app/"
pos: 1
roles:
- elliotweiser.osx-command-line-tools
- geerlingguy.mac.homebrew
- geerlingguy.mac.mas
- geerlingguy.mac.dock
================================================
FILE: tests/uninstall-homebrew.sh
================================================
#!/bin/bash
#
# Uninstalls Homebrew using the official uninstall script.
# Download and run the uninstall script.
curl -sLO https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh
chmod +x ./uninstall.sh
sudo ./uninstall.sh --force
# Clean up Homebrew directories.
sudo rm -rf /usr/local/Homebrew
sudo rm -rf /usr/local/Caskroom
sudo rm -rf /usr/local/bin/brew
sudo rm -rf /opt/homebrew
gitextract_x5j9spe2/
├── .ansible-lint
├── .github/
│ ├── FUNDING.yml
│ ├── stale.yml
│ └── workflows/
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── .yamllint
├── LICENSE
├── README.md
├── galaxy-deploy.yml
├── galaxy.yml
├── meta/
│ └── runtime.yml
├── plugins/
│ └── README.md
├── roles/
│ ├── dock/
│ │ ├── README.md
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ └── tasks/
│ │ ├── dock-add.yml
│ │ ├── dock-position.yml
│ │ ├── dock-remove.yml
│ │ └── main.yml
│ ├── homebrew/
│ │ ├── README.md
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ └── vars/
│ │ └── main.yml
│ └── mas/
│ ├── README.md
│ ├── defaults/
│ │ └── main.yml
│ └── tasks/
│ └── main.yml
└── tests/
├── ansible.cfg
├── inventory
├── requirements.yml
├── test.yml
└── uninstall-homebrew.sh
Condensed preview — 32 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (44K chars).
[
{
"path": ".ansible-lint",
"chars": 239,
"preview": "---\nexclude_paths:\n - galaxy-deploy.yml\n - .ansible/roles/*\nskip_list:\n - risky-file-permissions\n - yaml\n - fqcn-bu"
},
{
"path": ".github/FUNDING.yml",
"chars": 91,
"preview": "# These are supported funding model platforms\n---\ngithub: geerlingguy\npatreon: geerlingguy\n"
},
{
"path": ".github/stale.yml",
"chars": 2349,
"preview": "# Configuration for probot-stale - https://github.com/probot/stale\n\n# Number of days of inactivity before an Issue or Pu"
},
{
"path": ".github/workflows/ci.yml",
"chars": 2264,
"preview": "---\nname: CI\n'on':\n pull_request:\n push:\n branches:\n - master\n schedule:\n - cron: \"0 5 * * 0\"\n\ndefaults:\n "
},
{
"path": ".github/workflows/release.yml",
"chars": 774,
"preview": "---\nname: Release\n'on':\n push:\n tags:\n - '*'\n\ndefaults:\n run:\n working-directory: ansible_collections/geerl"
},
{
"path": ".gitignore",
"chars": 16,
"preview": "roles/.DS_Store\n"
},
{
"path": ".yamllint",
"chars": 320,
"preview": "---\nextends: default\n\nrules:\n line-length:\n max: 180\n level: warning\n comments:\n min-spaces-from-content: 1\n "
},
{
"path": "LICENSE",
"chars": 1053,
"preview": "Copyright 2021 Jeff Geerling\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this softw"
},
{
"path": "README.md",
"chars": 3339,
"preview": "# Mac Collection for Ansible\n\n[![MIT licensed][badge-license]][link-license]\n[![Galaxy Collection][badge-collection]][li"
},
{
"path": "galaxy-deploy.yml",
"chars": 1599,
"preview": "---\n# Automated release playbook for Ansible Collections.\n#\n# Originally based on Ericsysmin's 2020 blog post. Meant to "
},
{
"path": "galaxy.yml",
"chars": 1077,
"preview": "---\nnamespace: geerlingguy\nname: mac\nversion: \"1.2.0\"\nreadme: README.md\n\nauthors:\n - geerlingguy\n\ndescription: Collecti"
},
{
"path": "meta/runtime.yml",
"chars": 33,
"preview": "---\nrequires_ansible: \">=2.15.0\"\n"
},
{
"path": "plugins/README.md",
"chars": 844,
"preview": "# Collections Plugins Directory\n\nThis directory can be used to ship various plugins inside an Ansible collection. Each p"
},
{
"path": "roles/dock/README.md",
"chars": 2092,
"preview": "# Ansible Role: macOS Dock Automation\n\nThis role automates the use of `dockutil` to manage the items in your macOS Dock."
},
{
"path": "roles/dock/defaults/main.yml",
"chars": 381,
"preview": "---\n# Dock items to remove.\ndockitems_remove: []\n# - Launchpad\n# - TV\n# - Podcasts\n# - 'App Store'\n\n# Dock items to add."
},
{
"path": "roles/dock/tasks/dock-add.yml",
"chars": 1122,
"preview": "---\n- name: \"See if Dock item {{ item.name | default(item) }} exists.\"\n ansible.builtin.command: \"dockutil --find '{{ i"
},
{
"path": "roles/dock/tasks/dock-position.yml",
"chars": 722,
"preview": "---\n- name: \"Check the current Dock position of {{ item.name | default(item) }}.\"\n ansible.builtin.command:\n cmd: do"
},
{
"path": "roles/dock/tasks/dock-remove.yml",
"chars": 712,
"preview": "---\n- name: \"See if {{ item }} is in the Dock.\"\n ansible.builtin.command:\n cmd: dockutil --find '{{ item }}'\n regis"
},
{
"path": "roles/dock/tasks/main.yml",
"chars": 854,
"preview": "---\n- name: Install dockutil.\n community.general.homebrew:\n name: dockutil\n state: present\n notify:\n - Clear "
},
{
"path": "roles/homebrew/README.md",
"chars": 5659,
"preview": "# Ansible Role: Homebrew\n\nInstalls [Homebrew][homebrew] on MacOS, and configures packages, taps, and cask apps according"
},
{
"path": "roles/homebrew/defaults/main.yml",
"chars": 790,
"preview": "---\nhomebrew_repo: https://github.com/Homebrew/brew\n\nhomebrew_prefix: \"{{ (ansible_facts.machine == 'arm64') | ternary('"
},
{
"path": "roles/homebrew/handlers/main.yml",
"chars": 290,
"preview": "---\n# handlers for ansible-role-homebrew\n\n- name: Clear homebrew cache\n file:\n path: \"{{ homebrew_cache_path.stdout "
},
{
"path": "roles/homebrew/tasks/main.yml",
"chars": 6101,
"preview": "---\n- name: Determine Homebrew ownership variables\n set_fact:\n homebrew_user: '{{ homebrew_user | default(ansible_fa"
},
{
"path": "roles/homebrew/vars/main.yml",
"chars": 180,
"preview": "---\nhomebrew_folders_base:\n - Cellar\n - Frameworks\n - Caskroom\n - bin\n - etc\n - include\n - lib\n - opt\n - sbin\n "
},
{
"path": "roles/mas/README.md",
"chars": 4048,
"preview": "# Ansible Role: Mac App Store CLI (mas)\n\nInstalls [mas](https://github.com/mas-cli/mas) on macOS, and installs macOS app"
},
{
"path": "roles/mas/defaults/main.yml",
"chars": 488,
"preview": "---\nmas_email: \"\"\nmas_password: \"\"\nmas_uninstalled_apps: []\nmas_installed_app_ids: [] # Deprecated\nmas_installed_apps:\n "
},
{
"path": "roles/mas/tasks/main.yml",
"chars": 2175,
"preview": "---\n- name: Ensure MAS is installed.\n homebrew:\n name: mas\n state: present\n\n- name: Get MAS account status\n comm"
},
{
"path": "tests/ansible.cfg",
"chars": 62,
"preview": "[defaults]\ninventory = inventory\ncollections_path = ../../../\n"
},
{
"path": "tests/inventory",
"chars": 43,
"preview": "[local]\nlocalhost ansible_connection=local\n"
},
{
"path": "tests/requirements.yml",
"chars": 99,
"preview": "---\nroles:\n - name: elliotweiser.osx-command-line-tools\n\ncollections:\n - name: community.general\n"
},
{
"path": "tests/test.yml",
"chars": 794,
"preview": "---\n- name: Test the collection.\n hosts: localhost\n\n vars:\n homebrew_clear_cache: true\n\n homebrew_installed_pack"
},
{
"path": "tests/uninstall-homebrew.sh",
"chars": 404,
"preview": "#!/bin/bash\n#\n# Uninstalls Homebrew using the official uninstall script.\n\n# Download and run the uninstall script.\ncurl "
}
]
About this extraction
This page contains the full source code of the geerlingguy/ansible-collection-mac GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 32 files (40.1 KB), approximately 11.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.