Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 37 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<img src="https://raw.githubusercontent.com/geerlingguy/mac-dev-playbook/master/files/Mac-Dev-Playbook-Logo.png" width="250" height="156" alt="Mac Dev Playbook Logo" />

# Mac Development Ansible Playbook
# PRZM MacBook Development Ansible Playbook

[![CI][badge-gh-actions]][link-gh-actions]

Expand All @@ -9,15 +9,29 @@ This playbook installs and configures most of the software I use on my Mac for w
## Installation

1. Ensure Apple's command line tools are installed (`xcode-select --install` to launch the installer).
2. [Install Ansible](https://docs.ansible.com/ansible/latest/installation_guide/index.html):

1. Run the following command to add Python 3 to your $PATH: `export PATH="$HOME/Library/Python/3.9/bin:/opt/homebrew/bin:$PATH"`
2. Upgrade Pip: `sudo pip3 install --upgrade pip`
3. Install Ansible: `pip3 install ansible`

3. Clone or download this repository to your local drive.
4. Run `ansible-galaxy install -r requirements.yml` inside this directory to install required Ansible roles.
5. Run `ansible-playbook main.yml --ask-become-pass` inside this directory. Enter your macOS account password when prompted for the 'BECOME' password.
2. Install Homebrew (if not already installed):
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
After installation, follow the instructions to add Homebrew to your PATH (or open a new terminal).
3. Install Ansible via Homebrew:
```bash
brew install ansible
```
4. Clone this repository:
```bash
git clone https://github.com/goprzm/mac-dev-playbook.git
cd mac-dev-playbook
```
5. Install required Ansible roles:
```bash
ansible-galaxy install -r requirements.yml
```
6. Run the playbook:
```bash
ansible-playbook main.yml --ask-become-pass
```
Enter your macOS account password when prompted for the 'BECOME' password.

> Note: If some Homebrew commands fail, you might need to agree to Xcode's license or fix some other Brew issue. Run `brew doctor` to see if this is the case.

Expand Down Expand Up @@ -94,19 +108,27 @@ Any variable can be overridden in `config.yml`; see the supporting roles' docume

Applications (installed with Homebrew Cask):

- [1Password](https://1password.com/)
- [ChromeDriver](https://sites.google.com/chromium.org/driver/)
- [Docker](https://www.docker.com/)
- [Claude](https://claude.ai/)
- [Claude Code](https://www.anthropic.com/)
- [Cursor](https://cursor.sh/)
- [Dropbox](https://www.dropbox.com/)
- [Figma](https://www.figma.com/)
- [Firefox](https://www.mozilla.org/en-US/firefox/new/)
- [Google Chrome](https://www.google.com/chrome/)
- [Granola](https://www.granola.so/)
- [Handbrake](https://handbrake.fr/)
- [Homebrew](http://brew.sh/)
- [LICEcap](http://www.cockos.com/licecap/)
- [nvALT](http://brettterpstra.com/projects/nvalt/)
- [Loom](https://www.loom.com/)
- [Notion](https://www.notion.so/)
- [OrbStack](https://orbstack.dev/)
- [Sequel Ace](https://sequel-ace.com) (MySQL client)
- [Slack](https://slack.com/)
- [Spotify](https://www.spotify.com/)
- [Sublime Text](https://www.sublimetext.com/)
- [Transmit](https://panic.com/transmit/) (S/FTP client)
- [Visual Studio Code](https://code.visualstudio.com/)

Packages (installed with Homebrew):

Expand All @@ -127,6 +149,8 @@ Packages (installed with Homebrew):
- node
- nvm
- php
- pngpaste
- pscale
- ssh-copy-id
- readline
- openssl
Expand Down
31 changes: 28 additions & 3 deletions default.config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
configure_dotfiles: true
configure_terminal: true
configure_osx: true
configure_macos_settings: true

# Accept apps that were installed outside of Homebrew (adopts existing apps).
homebrew_cask_accept_external_apps: true

# Development setup configuration.
configure_development_setup: true
przm_repo: https://github.com/goprzm/przm.git
przm_repo_version: master
open_vscode_after_clone: true
open_orbstack_after_setup: true
open_granola_after_setup: true
open_claude_after_setup: true
open_1password_after_setup: true
desktop_color: Black # Options: Black, Silver, Stone, Teal, Space Gray, etc.

# Set to 'true' to configure the Dock via dockutil.
configure_dock: false
Expand Down Expand Up @@ -49,10 +64,10 @@ homebrew_installed_packages:
- libevent
- sqlite
- nmap
- node
- nvm
- asdf # Version manager for node, pnpm, etc. Uses .tool-versions
- php
- pngpaste
- pscale
- ssh-copy-id
- readline
- openssl
Expand All @@ -65,17 +80,27 @@ homebrew_taps: []

homebrew_cask_appdir: /Applications
homebrew_cask_apps:
- 1password
- chromedriver
- docker
- claude
- claude-code
- cursor
- dropbox
- figma
- firefox
- google-chrome
- granola
- handbrake
- licecap
- loom
- notion
- orbstack
- sequel-ace
- slack
- spotify
- sublime-text
- transmit
- visual-studio-code

# See `geerlingguy.mac.mas` role documentation for usage instructions.
mas_installed_apps: []
Expand Down
17 changes: 17 additions & 0 deletions main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
- name: Configure host.
hosts: all

vars_prompt:
- name: git_user_name
prompt: "Enter your full name"
private: false

- name: work_email
prompt: "Enter your work email"
private: false

vars_files:
- default.config.yml

Expand Down Expand Up @@ -46,6 +55,14 @@
when: configure_sublime
tags: ['sublime-text']

- import_tasks: tasks/development-setup.yml
when: configure_development_setup
tags: ['development-setup']

- import_tasks: tasks/macos-settings.yml
when: configure_macos_settings
tags: ['macos-settings']

- name: Run post-provision task files in a block.
tags: ['post']
block:
Expand Down
198 changes: 198 additions & 0 deletions tasks/development-setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
---
- name: Ensure ~/Development directory exists.
file:
path: ~/Development
state: directory
mode: "0755"

- name: Configure git global user email.
community.general.git_config:
name: user.email
scope: global
value: "{{ work_email }}"

- name: Configure git global user name.
community.general.git_config:
name: user.name
scope: global
value: "{{ git_user_name }}"

- name: Check GitHub CLI authentication status.
command: gh auth status
register: gh_auth_status
changed_when: false
failed_when: false

- name: Prompt user to authenticate with GitHub CLI.
when: gh_auth_status.rc != 0
block:
- name: Display GitHub authentication instructions.
pause:
prompt: |

╔════════════════════════════════════════════════════════════════╗
║ GitHub CLI authentication required ║
╠════════════════════════════════════════════════════════════════╣
║ Please open a NEW terminal window and run: ║
║ ║
║ gh auth login ║
║ ║
║ Once authenticated, press ENTER here to continue... ║
╚════════════════════════════════════════════════════════════════╝

- name: Verify GitHub CLI authentication after prompt.
command: gh auth status
changed_when: false

- name: Configure gh git protocol to use https.
command: gh config set git_protocol https
changed_when: false

- name: Setup gh as git credential helper.
command: gh auth setup-git
changed_when: false

- name: Clone PRZM repository.
git:
repo: "{{ przm_repo }}"
dest: ~/Development/przm
version: "{{ przm_repo_version }}"
accept_hostkey: true
register: przm_clone_result
ignore_errors: true

- name: Display clone result.
debug:
msg: "PRZM repository cloned successfully to ~/Development/przm"
when: przm_clone_result is succeeded

- name: Add asdf initialization to shell config.
blockinfile:
path: ~/.zshrc
marker: "# {mark} ANSIBLE MANAGED - asdf"
block: |
# asdf version manager
source $(brew --prefix asdf)/libexec/asdf.sh
insertafter: EOF

- name: Add pnpm completion to shell config.
blockinfile:
path: ~/.zshrc
marker: "# {mark} ANSIBLE MANAGED - pnpm completion"
block: |
# pnpm shell completion
source <(pnpm completion zsh)
insertafter: EOF

- name: Add ~/.local/bin to PATH for Claude Code and other local binaries.
blockinfile:
path: ~/.zshrc
marker: "# {mark} ANSIBLE MANAGED - local bin path"
block: |
# Add ~/.local/bin to PATH (for Claude Code native installation, etc.)
export PATH="$HOME/.local/bin:$PATH"
insertafter: EOF

- name: Add asdf shims to PATH for npm/pnpm/npx availability.
blockinfile:
path: ~/.zshrc
marker: "# {mark} ANSIBLE MANAGED - asdf shims"
block: |
# Ensure asdf shims are in PATH for npm, pnpm, npx, node
export PATH="$HOME/.asdf/shims:$PATH"
insertafter: EOF

- name: Run claude install to configure Claude Code.

Check failure on line 105 in tasks/development-setup.yml

View workflow job for this annotation

GitHub Actions / Lint

ignore-errors

Use failed_when and specify error conditions instead of using ignore_errors.

Check failure on line 105 in tasks/development-setup.yml

View workflow job for this annotation

GitHub Actions / Lint

ignore-errors

Use failed_when and specify error conditions instead of using ignore_errors.
shell: |
export PATH="$HOME/.local/bin:/opt/homebrew/bin:$PATH"
if command -v claude &> /dev/null; then
claude install --yes 2>/dev/null || true
fi
args:
executable: /bin/zsh
changed_when: false
ignore_errors: true

- name: Check if przm repo exists.
stat:
path: ~/Development/przm/.tool-versions
register: przm_tool_versions

- name: Add asdf plugins for nodejs and pnpm.
shell: |
source $(brew --prefix asdf)/libexec/asdf.sh
asdf plugin add nodejs || true
asdf plugin add pnpm || true
args:
executable: /bin/zsh
changed_when: false
when: przm_tool_versions.stat.exists

- name: Install tools from .tool-versions via asdf.
shell: |
source $(brew --prefix asdf)/libexec/asdf.sh
cd ~/Development/przm
asdf install
args:
executable: /bin/zsh
when: przm_tool_versions.stat.exists

- name: Get GitHub token from gh CLI for MCP server.
command: gh auth token
register: gh_token_result
changed_when: false
failed_when: false

- name: Check if .env.local exists in przm repo.
stat:
path: ~/Development/przm/.env.local
register: przm_env_local

- name: Create .env.local with GitHub PAT if it doesn't exist.
copy:
dest: ~/Development/przm/.env.local
content: |
# GitHub Personal Access Token for MCP server
GITHUB_PERSONAL_ACCESS_TOKEN={{ gh_token_result.stdout }}
mode: "0600"
when:
- gh_token_result.rc == 0
- gh_token_result.stdout | length > 0
- not przm_env_local.stat.exists

- name: Add GitHub PAT to existing .env.local if not present.
lineinfile:
path: ~/Development/przm/.env.local
line: "GITHUB_PERSONAL_ACCESS_TOKEN={{ gh_token_result.stdout }}"
regexp: "^GITHUB_PERSONAL_ACCESS_TOKEN="
state: present
mode: "0600"
when:
- gh_token_result.rc == 0
- gh_token_result.stdout | length > 0
- przm_env_local.stat.exists

- name: Open VSCode with PRZM repository.
command: open -a "Visual Studio Code" ~/Development/przm
changed_when: false
when: open_vscode_after_clone

- name: Open OrbStack.
command: open -a "OrbStack"
changed_when: false
when: open_orbstack_after_setup

- name: Open Granola.
command: open -a "Granola"
changed_when: false
when: open_granola_after_setup

- name: Open Claude.
command: open -a "Claude"
changed_when: false
when: open_claude_after_setup

- name: Open 1Password.
command: open -a "1Password"
changed_when: false
when: open_1password_after_setup
Loading
Loading